Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Trying to run tests with PHPUnit results in this error:
[08-Mar-2020 04:03:27 Australia/Sydney] PHP Fatal error: Cannot declare class Drupal\Tests\Core\Theme\TestRegistry, because the name is already in use in /Users/paul/projects/drupal/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php on line 493
This is because Drupal\Tests\Core\Theme\RegistryTest
and Drupal\Tests\Core\Theme\RegistryLegacyTest
both define a class called Drupal\Tests\Core\Theme\TestRegistry
, and they're both declared during test discovery.
This error does not happen during run-tests.sh because Drupal's bespoke test discovery system does not load classes.
Proposed resolution
Use mock objects to meet the needs of the tests.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
Comment | File | Size | Author |
---|---|---|---|
#16 | interdiff.txt | 1.15 KB | Mile23 |
#16 | 3118477_16.patch | 5.39 KB | Mile23 |
#11 | interdiff_8-10.txt | 744 bytes | mondrake |
#11 | 3118477-10.patch | 5.02 KB | mondrake |
#11 | 3118477-10-test-only.patch | 1 KB | mondrake |
Comments
Comment #2
Mile23Have a patch.
I'm pretty sure we should nuke get_defined_functions() as well, but the tests run without error without removing it, so there we are.
Comment #3
Mile23Comment #4
Mile23I spoke too soon.
Only
RegistryTest
needsget_defined_functions()
, so we can just delete it fromRegistryLegacyTest
, kicking the can into the future. :-)Comment #5
mondrakeSince the issue of PHPUnit CLI testing breaking is recurring quite frequently, I thought it would be good to add a test to prevent regressions. The problem is that DrupalCI, through run-tests.sh, runs tests one at a time indicating a test file at each run. That prevents PHPUnit's own test discovery mechanism to execute. However, that is exactly the mechanism that runs at the time of testing through CLI (which we are recommending more and more over run-tests.sh, btw), and that mechanisms autoload classes across different files - and that's when collisions happen.
The test here is inspired by BuildTestBase.
Comment #6
Mile23Generally +1 on exercising the cli. I'd suggest that we can do the test discovery part without the test running part by calling
phpunit -c core --list-tests
. Also it could be a build test which has handy assertions for processes already.Comment #8
mondrake#6:
Done that.
I tried that but failed to make it work... anyone feel free to take it on if you deem it relevant.
Comment #9
mondrakeComment #10
mondrakeComment #11
mondrakeSorry.
Comment #12
alexpottI don't think this is the right approach. Running all our unit tests again to prove that they are all runnable as one feels way off. Either we do that or we do tun-tests.sh but doing both feels very Drupal.
Also why is this a critical task. If running a single PHPUnit test from the command line was broken I'd agree but it is not. This are only broken when you run core/tests/Drupal/Tests/Core/Theme/RegistryLegacyTest.php and core/tests/Drupal/Tests/Core/Theme/RegistryTest.php in the same PHPUnit run.
Comment #13
mondrake#12 with
--list-tests
we just discover the tests, without running them. Test discovery is enough to autoload all test classes by PHPUnit CLI and show the problem.right - major given Cause test failures in environments not supported by the automated testing platform. in Priority levels of issues.
Anyway, this comes from #3109480: Properly deprecate theme functions for Drupal 10 which is a committed critical, half way being backported to 8.x.
Comment #14
catchI don't think this is helpful as a core test, it is extremely meta. If we really want to add this as a linting thing, we could add it to DrupalCI itself?
Comment #16
Mile23Yesterday I was going to work on this composer initiative issue: #3047468: Create a tool to convert a non-Composer-based Drupal to a Composer-based one But instead I worked on this blocker issue because there's only so much time in the day. It's a blocker in that I can't run tests, and I run a lot of tests when I work.
#3109480: Properly deprecate theme functions for Drupal 10 introduced a regression, and so therefore we should test to make sure we don't re-introduce a similar regression in the future. We've had plenty of these in the past. Keep in mind, folks: We have mocking frameworks for a reason. :-)
If there's a better way to prevent this regression than exercising the test suites, then let's do that. But for now, here's basically the same patch with some nicer docs.
@mondrake is right and turning the test into a build test would involve calling copyCodebase(), which would add a bunch of file copies to the run time of this test, so let's not do that.
Comment #17
neclimdulYou're my hero...Not the prettiest or most complete test but that covers a solid basic lint that will be very helpful and a complete test would be using the runner so yeah... :)
@catch I'd love for DrupalCI to do phpunit testing but after like 5 years of my CI being randomly broken and pushing for using the phpunit runner in testing discussions with no movement.. for things like this I'd love to have at least this basic test. The right fix is such a big lift and this is small and should save a lot of headaches from a class of bugs.
This fixes things so I can run tests and coverage for core issues again, avoids regressions, and passes so RTBC imho.
Comment #18
longwaveAs we are removing this I think we can get rid of all references to $functions in the RegistryLegacyTest class as well.
+1 to adding PhpUnitCliTest to avoid this sort of copy paste error in the future, this was my fault originally so apologies for that :)
Comment #19
alexpottI'm not a huge fan of the test. Because I fear that it'll add noise to the test runs doing double fails. But as it is only listing tests I guess it is better than nothing. I dunno I guess time will tell.
Committed and pushed 0a65cd6076 to 9.0.x and ad2edda33d to 8.9.x. Thanks!
I cleaned up $functions in the legacy test as this change removes its purpose.
Run the test locally - it's fine.
I also fixed the following coding standards: