Problem/Motivation

Looks like ctools recently introduced some new tests which seem to have an undeclared dependency on views.

See e.g. https://www.drupal.org/pift-ci-job/1963329

PHP Fatal error:  Class 'ViewsSqlTest' not found in /var/www/html/sites/all/modules/ctools/views_content/tests/src/views_content.test on line 11

The new tests were part of #3181701: 'More' link in Content pane display broken

Steps to reproduce

On a site with ctools but where views is completely absent (i.e. not on disk):

$ php scripts/run-tests.sh --list
Error: Class 'ViewsSqlTest' not found in include_once() (line 11 of /drupal-7.x/sites/all/modules/contrib/ctools/views_content/tests/src/views_content.test).

Proposed resolution

It actually looks like this is not truly an undeclared dependency, as the views_content submodule declares its dependency on views, as does the ViewsContentPanesTest class within its getInfo method.

However, simpletest seems to hit an exception when it tries to load the class to check its dependencies because the signature extends a class which may not exist.

There are probably a few different ways to avoid this - one is the pattern described here: https://stackoverflow.com/a/17325203

Remaining tasks

Work out how to fix this, do the patch dance etc..

User interface changes

n/a

API changes

n/a

Data model changes

n/a

Comments

mcdruid created an issue. See original summary.

mcdruid’s picture

TIL: https://www.drupal.org/docs/7/creating-custom-modules/writing-module-inf...

Looks like you can add test_dependencies which drupalci will pull in.

So perhaps adding views as a test_dependency for the views_content submodule would fix this?

Hmm but views is already declared as a dependency there actually.

So is this more a problem with drupalci? I'll look into that some more.

mcdruid’s picture

I don't think this is specific to drupalci - I get the same thing locally if views is not available:

$ php scripts/run-tests.sh --list
Error: Class 'ViewsSqlTest' not found in include_once() (line 11 of /drupal-7.x/sites/all/modules/contrib/ctools/views_content/tests/src/views_content.test).
mcdruid’s picture

AFAICS simpletest tries to skip test classes which have unmet dependencies:

https://git.drupalcode.org/project/drupal/-/blob/7.78/modules/simpletest...

However, it looks like calling class_exists() on ViewsContentPanesTest causes the exception as it extends a non-existent class... so its getInfo method doesn't get a chance to declare its dependency on views - which looks like it would probably result in the class being skipped.

So I think unless we're going to try and fix this in D7 core / simpletest, it'd be up to ctools to avoid this problem.

One option might be something like this: https://stackoverflow.com/a/17325203

...which seems a bit of a hack, but may avoid the problem outlined above?

mcdruid’s picture

Status: Active » Needs review
StatusFileSize
new940 bytes

This seems to work AFAICS; it allows run-tests.sh / simpletest_test_get_all() to examine the class in order to decide (via getInfo) that it has unmet dependencies and should be skipped.

mcdruid’s picture

Issue summary: View changes
mcdruid’s picture

Issue summary: View changes
mcdruid’s picture

Some extra details about exactly how to reproduce this; you need to have ctools on disk but not views (which is the state drupalci creates when it's testing a module that depends on ctools but not views).

Example:

$ drush -y si && drush -y en simpletest
You are about to DROP all tables in your 'drupal7x' database. Do you want to continue? (y/n): y
Starting Drupal installation. This takes a while. Consider using the --notify global option.
Installation complete.  User name: the-head-honcho  User password: 2tCDV2fqGW
The following extensions will be enabled: simpletest
Do you really want to continue? (y/n): y
simpletest was enabled successfully.
simpletest defines the following permissions: administer unit tests

$ drush pml | grep 'views\|ctools'
 Chaos tool suite                     Chaos tools (ctools)                                         Module  Not installed  7.x-1.19
 Chaos tool suite                     Chaos Tools (CTools) AJAX Example (ctools_ajax_sample)       Module  Not installed  7.x-1.19
 Chaos tool suite                     Chaos Tools (CTools) Plugin Example (ctools_plugin_example)  Module  Not installed  7.x-1.19
 Chaos tool suite                     Custom content panes (ctools_custom_content)                 Module  Not installed  7.x-1.19
 Chaos tool suite                     Custom rulesets (ctools_access_ruleset)                      Module  Not installed  7.x-1.19
 Chaos tool suite                     Views content panes (views_content)                          Module  Not installed  7.x-1.19

 $ php scripts/run-tests.sh --list
Error: Class 'ViewsSqlTest' not found in include_once() (line 11 of /drupal-7.x/sites/all/modules/contrib/ctools/views_content/tests/src/views_content.test).

If views is there in the modules directory, the problem doesn't happen (I'm guessing this is down to autoloading).

megachriz’s picture

I think that this fix is acceptable. I remember to have it seen in other modules in test classes.

Not in test classes, but a similar pattern to fix a problem like this:
https://git.drupalcode.org/project/date/-/blob/7.x-2.x/date.migrate.inc
https://git.drupalcode.org/project/rules/-/blob/7.x-2.x/includes/faces.inc

mcdruid’s picture

Issue summary: View changes
StatusFileSize
new4.65 KB

Thanks for the examples @MegaChriz

Here's a patch with the simpler approach of just wrapping the whole class a check for the views class:

if (class_exists('ViewsSqlTest')) {
  class ViewsContentPanesTest extends ViewsSqlTest {
    // stuff
  }
}

The extra indentation meant a comment needed to tweaked, but that's the only other change.

I prefer this to the middle-class hack.

mcdruid’s picture

StatusFileSize
new473 bytes
new322 bytes

Discussed this in chat with @mixologic, @joelpittet and @MegaChriz.

There are (at least) two options:

There are a few different ways to do the workaround in the class file, but @joelpittet expressed a preference for the pattern used in date.migrate.inc in the example @MegaChriz provided in #9. It's quite minimal and avoids messing about with indentation.

@mixalogic confirmed that adding the test dependency will not work in a patch (we tried in #2796511-10: Custom headers); the change has to be committed to the .info file for drupalci to act upon it.

Here are patches for those two options; either ought to fix the problem. Steps to reproduce are in #8. It may be sufficient to clear caches between tests if you want to avoid a full reinstall every time.

N.B. testing manually won't confirm whether the test dependency fixes the problem, but you can simulate it by putting views into the modules directory.

It's up to the maintainers which approach they prefer.

mcdruid’s picture

Also, for posterity, @mixologic confirmed that drupalci will not pick up dependencies from submodules (which are themselves a bit of a hack).

joelpittet’s picture

Status: Needs review » Fixed

I went with early return, I'd rather not add a test dependency for a submodule in the root module as I suspect that will have a performance issue and maybe others around including that while running tests.

Thanks for all your efforts on this!

  • joelpittet committed 8821f31 on 7.x-1.x authored by mcdruid
    Issue #3196169 by mcdruid, MegaChriz: PHP Fatal error:  Class '...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

joseph.olstad’s picture

this also came up in facetapi

#3230219: test bot failure