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

CommentFileSizeAuthor
#6 _3549601_1.run-tests-d11-2.patch3.3 KBjonathan1055

Issue fork drupal-3549601

Command icon 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

jonathan1055 created an issue. See original summary.

jonathan1055’s picture

I have pushed an initial commit to the MR. I'm utilising the existing --debug-discovery argument 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.

jonathan1055’s picture

Interesting 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_TOTAL

but the test failed due to an unexpected value for test_names

    [test_names] => Array
        (
            [0] => 1
        )

This would normally be either empty, or a test group or a class or module, but not "1". Then we also see

[ci-parallel-node-index] => --ci-parallel-node-total
[ci-parallel-node-total] => 1

so this implies to me that $CI_PARALLEL_NODE_INDEX is 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.

mondrake’s picture

I 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.

jonathan1055’s picture

StatusFileSize
new3.3 KB

Thanks @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

jonathan1055’s picture

Status: Active » Needs review

I have pushed a one-line fix for the empty CI_PARALLEL_NODE_INDEX, adding

# If CI_PARALLEL_NODE_INDEX is empty set it to 1 so that the argument parsing works correctly.
CI_PARALLEL_NODE_INDEX=${CI_PARALLEL_NODE_INDEX:-1}

and 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.

mondrake’s picture

Nice. I have added some comments inline.

jonathan1055’s picture

Thanks. 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_access
https://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 --directory in the command
https://git.drupalcode.org/issue/webform-3547627/-/pipelines/616992 - phpunit runs just the small subset of tests and passes.

mondrake’s picture

OK I'll open a new MR so I do not pollute your work, then

mondrake’s picture

Funnily, it looks like PHPUnit\TextUI\Configuration\TestSuiteBuilder is 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.

jonathan1055’s picture

OK I'll open a new MR so I do not pollute your work, then

I 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.

mondrake’s picture

Thanks, 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.

jonathan1055’s picture

Thank 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.sh are, 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.

mondrake’s picture

I’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.

smustgrave’s picture

@mondrake should this be NW per your last comment for tests?

mondrake’s picture

@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.

smustgrave’s picture

Status: Needs review » Postponed

Thank you for following up!

mondrake’s picture

Issue tags: +run-tests.sh
jonathan1055’s picture

As 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 mymodule in favor of #[Group('mymodule')].

Do we have a plan for which run-tests.sh issues are being worked on, and in what order?

mondrake’s picture

No 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.

jonathan1055’s picture

Adding meta parent

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

wim leers’s picture

jonathan1055’s picture

Rebased this MR, and it appears that the file .gitlab-ci/pipeline.yml is 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 #7
https://git.drupalcode.org/issue/drupal-3549601/-/jobs/8752436#L75

mondrake’s picture

jonathan1055’s picture

Yes, just found it. So I should probably re-do that single line change in the .gitlan-ci.yml file, which looks like is being used instead of the deleted one

@@ -163,13 +229,12 @@ default:
 # If any job in the stage fails, the pipeline will exit early.
 ################
 
-.default-stage: &default-stage
-  stage: 🗜️ Test
+.recursive-trigger: &recursive-trigger
+  stage: 🗜️ Additional tests
   trigger:
     # Rely on the status of the child pipeline.
     strategy: depend
-    include:
-      - local: .gitlab-ci/pipeline.yml
+    include: .gitlab-ci.yml
 
 .run-on-commit: &run-on-commit
   rules:
jonathan1055’s picture

I 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_TOTAL

now
--ci-parallel-node-index $CI_NODE_INDEX --ci-parallel-node-total $CI_NODE_TOTAL

I have pushed a second change, but if the variable rename was accidental, let me know and we can fix it the other way.

mondrake’s picture

mondrake’s picture

Status: Postponed » Active

Blocker is in.

mondrake’s picture

Status: Active » Needs review

Refreshed and added tests.

jonathan1055’s picture

Thanks for the rebases. I will re-visit the contrib testing I did in #9 to check that it works like before.