Problem/Motivation
When using core/scripts/run-tests.sh with a final argument to run just a subset of tests for a specific @group the test discovery process can fail with errors such as "class not found" or "declaration ... must be compatible with ..." in unrelated 3rd-party modules. The tests in these modules are never intended to be run, so the errors are not actually relevent. However the job is halted, thus preventing the tests in the actual project from being run.
The error does not happen for Drupal Core 10 and 11.0 and 11.1, which use PHPUnit 10. The problem starts with core version 11.2 which has PHPUnit 11 and where run-tests.sh has been modified to use the new test discovery API.
The problem does not happen if the --directory parameter is specified, as this limits the test discovery to just the module being tested, or a folder within it, so the 3rd-party modules file are never examined. But the problem then is that this overrides the @group argument and all tests are run. The --directory and @group filtering can be made to work together and not be mutually exclusive, such that --directory will limit the test discovery then @group filtering will be used to run the subset of tests.
Gitlab Templates can be modified to add the --directory parameter when required, and this will greatly help all contrib modules who are testing with a subset of tests.
A secondary benefit of this is that it is much much faster locally to scan only the module you are testing, not the entire set of source test files for every module in your site.
Steps to reproduce
Here is an example in the webform modules where an error in the feeds module prevents the tests from running.
https://git.drupalcode.org/issue/webform-3547627/-/jobs/6632522#L389
Here is an example in Gitlab Templates development, when an error in the sam module is preventing testing a recipe, which uses a core recipe, which loads the sam module
https://git.drupalcode.org/project/gitlab_templates_downstream/-/jobs/67...
Proposed resolution
Add $args['module'] and $args['directory'] when calling findAllClassFiles() then filter later for test groups if required.
Remaining tasks
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|
Issue fork drupal-3549601
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
jonathan1055 commentedI have pushed an initial commit to the MR. I'm utilising the existing
--debug-discoveryargument to give further debug output to show what it happening. Some of this debug could stay, other bits will be deleted.I will use the diff url from this MR to download and apply the patch, to deminstrate it in contrib testing.
Comment #4
jonathan1055 commentedInteresting with the PHPUnit Build failed job, the command is
sudo -u www-data -E -H php ./core/scripts/run-tests.sh --phpunit-configuration $PHPUNIT_CONFIGURATION_FILE_PATH --debug-discovery --color --keep-results --types "$TESTSUITE" --concurrency "$CONCURRENCY" --repeat "1" --sqlite "./sites/default/files/tests.sqlite" --dburl $SIMPLETEST_DB --url $SIMPLETEST_BASE_URL --verbose --non-html --all --ci-parallel-node-index $CI_PARALLEL_NODE_INDEX --ci-parallel-node-total $CI_PARALLEL_NODE_TOTALbut the test failed due to an unexpected value for test_names
This would normally be either empty, or a test group or a class or module, but not "1". Then we also see
so this implies to me that
$CI_PARALLEL_NODE_INDEXis unintentionally empty, thus shuffling the value along so it reads the string "--ci-parallel-node-total" as the value. This means we get left with a "1" which is taken to be a test group (positional parameter) and that causes the $group array to be filtered for the test called "1", so we end up with no tests found.Comment #5
mondrakeI also found the problem described in #4. Doing #3536964: run-tests.sh - segregate command line parsing and use Symfony Console classes would help here, Symfony’s argv parsing logic is very robust.
Comment #6
jonathan1055 commentedThanks @mondrake for the link. I've followed that issue.
To allow testing in Gitlab pipelines here is a static patch file for core 11.2 as there have been some changes in 11.x (11.3) which clash when trying to apply using https://git.drupalcode.org/project/drupal/-/merge_requests/13363.diff
Comment #7
jonathan1055 commentedI have pushed a one-line fix for the empty
CI_PARALLEL_NODE_INDEX, addingand that has fixed all of the failing core pipeline tests :-)
This is ready for review and feedback. I have also used this patch in contrib jobs that were failing due to 3rd-party Test Discovery errors, and now they pass. I'll add links to them here.
Comment #8
mondrakeNice. I have added some comments inline.
Comment #9
jonathan1055 commentedThanks. I've replied in the threads.
Here is a test on the Webform module, submitted via UI just trying to run with
_PHPUNIT_TESTGROUPS = webform_accesshttps://git.drupalcode.org/issue/webform-3547627/-/pipelines/616970 - it fails as expected becuase of errors in the Feed module test files
Now the same UI pipeline, but using Gitlab Tempates MR410, which applies the patches from here and add
--directoryin the commandhttps://git.drupalcode.org/issue/webform-3547627/-/pipelines/616992 - phpunit runs just the small subset of tests and passes.
Comment #10
mondrakeOK I'll open a new MR so I do not pollute your work, then
Comment #11
mondrakeFunnily, it looks like
PHPUnit\TextUI\Configuration\TestSuiteBuilderis not using the groups passed in configuration to pre-filter the test - all tests are discovered regardless of their group based on the testsuite, and then only those not part of the specified groups skipped while executing them (all PHPUnit internals here, I mean). So... maybe we just move the logic to PhpUnitTestDiscovery instead.Comment #12
jonathan1055 commentedI have a static patch of the work done so far, so I can use that in other jobs, and for reference, so I'm fine with you using this MR, then we can see the further changes you do from this point. Core has enough redundant MRs already :-) But if you want to start again that's OK too.
Comment #13
mondrakeThanks, I've added a new commit on the existing MR then. The idea is to not add the logic to run-tests.sh but to the discovery class. In general, I'd rather take away as much as possible from run-tests.sh into task specific classes. There are a few issues open already for that.
Comment #14
jonathan1055 commentedThank you. That's a better way to do it. Much cleaner to read. I will test in a real contrib pipeline, but as you said before this could also have a build test. I don't know where the tests for
run-tests.share, but if you point me there I could look at expanding to add coverage for this. Or if you can do it easily and quickly then carry on and do so.Comment #15
mondrakeI’ll add tests, no worries. But I’d rather like the referenced issue be done first, so if you can please review it and its blocker.
There are no tests for run-tests.sh… that’s why people including me have been trying to move away its logic in separate testable classes.
Comment #16
smustgrave commented@mondrake should this be NW per your last comment for tests?
Comment #17
mondrake@smustgrave yes, or postponed on the referenced. There are already a bunch of issues about run-tests.sh that are not moving, alas, let's not add more.
Comment #18
smustgrave commentedThank you for following up!
Comment #19
mondrakeComment #20
jonathan1055 commentedAs per #16-18 this issue is postponed on #3536964: run-tests.sh - segregate command line parsing and use Symfony Console classes
But the error in run-tests.sh test discovery that is being solved here is now causing actual test failures in contrib, now that some 3rd-party modules have dropped using
@group mymodulein favor of#[Group('mymodule')].Do we have a plan for which run-tests.sh issues are being worked on, and in what order?
Comment #21
mondrakeNo plan really... these run-tests.sh related issues are a pain to move forward, but each can move on its own. For me #3515347: Reduce run-tests.sh complexity in spawning subprocesses is kind blocking others that I am planning to work on. Feel free to unpostpone and bring this one forward if you want.
Comment #22
jonathan1055 commentedAdding meta parent
Comment #24
wim leersRelated GitLab Templates issue: https://git.drupalcode.org/project/gitlab_templates/-/issues/3548261#not...
Comment #25
jonathan1055 commentedRebased this MR, and it appears that the file
.gitlab-ci/pipeline.ymlis no longer in 'main' branch. Or more likely it's been moved or remaned. Hence the one-line fix I had to add before has got lost, and we get a recurence of the test failures as described in #4 above and fixed in #7https://git.drupalcode.org/issue/drupal-3549601/-/jobs/8752436#L75
Comment #26
mondrakeThat file was removed in #3572375: [ci] Run tests in top level pipeline, use recursion for secondary test runs
Comment #27
jonathan1055 commentedYes, just found it. So I should probably re-do that single line change in the
.gitlan-ci.ymlfile, which looks like is being used instead of the deleted oneComment #28
jonathan1055 commentedI replicated the change from before, but it still failed. Then I spoted that the variable names has also changed:
before
--ci-parallel-node-index $CI_PARALLEL_NODE_INDEX --ci-parallel-node-total $CI_PARALLEL_NODE_TOTALnow
--ci-parallel-node-index $CI_NODE_INDEX --ci-parallel-node-total $CI_NODE_TOTALI have pushed a second change, but if the variable rename was accidental, let me know and we can fix it the other way.
Comment #29
mondrakeWhen #3536964: run-tests.sh - segregate command line parsing and use Symfony Console classes is committed, you won't have to care anymore.
Comment #30
mondrakeBlocker is in.
Comment #31
mondrakeRefreshed and added tests.
Comment #32
jonathan1055 commentedThanks for the rebases. I will re-visit the contrib testing I did in #9 to check that it works like before.