Problem/Motivation
tl;dr
Currently, if you run core's phpunit-based tests using phpunit
, it will find and load traits for tests in contrib modules. If you do the same thing using TestDiscovery
, it won't. That's because TestDiscovery
currently only allows specific namespaces per module per test type, without allowing autoloading of the whole of the test namespace. So for instance if you have a Unit
test and a Functional
test and you define a trait for both of them to use, then TestDiscovery
won't allow for autoloading that trait.
That's the problem we're trying to solve in this issue, in harmony with the principles in #123.
The solution is that we have TestDiscovery
register the whole test namespace for autoloading, which creates a new problem: This allows autoloading of tests which don't fit into the categories core knows how to run.
My early solution to that problem was to throw an exception. @Torenware kept the exception, but added a category for 'Unclassified' that could be used for non-Core modules; the exceptions enforced the new set-up for Core, but not for Contrib. @alexpott added a test suite for 'unclassified', which puts some edges on where these unclassified tests should be in the file system; this approach treats Core and Contrib the same.
While factoring a complicated set of mocks for the file_example module in Examples, I've discovered that run-tests.sh cannot find a trait that is in the
Drupal\Tests
when the trait is used in a PHPUnit test. The same tests run fine if run directly via ../vendor/bin/phpunit.I've put together a demo that shows the problem. The test module lays out its files as so:
test_traits_in_tests/ ├── src │ └── NotTestTrait.php ├── test_traits_in_tests.info.yml ├── test_traits_in_tests.module └── tests └── src ├── TestTrait.php └── Unit ├── AnotherTrivialTest.php └── TrivialTest.php
TrivialTest uses TestTrait, and AnotherTrivialTest uses NotTestTrait. Except for their namespacing and use statements the two tests and the two traits are identical.
Running phpunit from the command line:
vagrant@drupalvm3:/var/www/drupal/core$ ../vendor/bin/phpunit ../modules/custom/test_traits_in_tests/ PHPUnit 4.8.11 by Sebastian Bergmann and contributors. .. Time: 23.53 seconds, Memory: 6.75Mb OK (2 tests, 2 assertions)
Using run-test.sh, however, TrivialTest crashes:
vagrant@drupalvm3:/var/www/drupal/core$ php scripts/run-tests.sh --url http://192.168.88.42/drupal/ --module test_traits_in_tests Drupal test run --------------- Tests to be run: - Drupal\Tests\test_traits_in_tests\Unit\AnotherTrivialTest - Drupal\Tests\test_traits_in_tests\Unit\TrivialTest Test run started: Saturday, October 31, 2015 - 22:04 Test summary ------------ Drupal\Tests\test_traits_in_tests\Unit\AnotherTrivialTest 1 passes PHP Fatal error: Trait 'Drupal\Tests\test_traits_in_tests\TestTrait' not found in /var/www/drupal/modules/custom/test_traits_in_tests/tests/src/Unit/TrivialTest.php on line 22 PHP Stack trace: PHP 1. {main}() /var/www/drupal/core/scripts/run-tests.sh:0 PHP 2. simpletest_script_run_one_test() /var/www/drupal/core/scripts/run-tests.sh:42 PHP 3. spl_autoload_call() /var/www/drupal/core/scripts/run-tests.sh:649 PHP 4. Symfony\Component\ClassLoader\ApcClassLoader->loadClass() /var/www/drupal/core/scripts/run-tests.sh:0 PHP 5. require() /var/www/drupal/vendor/symfony/class-loader/ApcClassLoader.php:114 Fatal error: Trait 'Drupal\Tests\test_traits_in_tests\TestTrait' not found in /var/www/drupal/modules/custom/test_traits_in_tests/tests/src/Unit/TrivialTest.php on line 22
Since factoring tests is a good thing, we ought to support this.
Proposed resolution
Currently our bootstrap.php
for PHPunit autoloads from tests/src
whereas simpltest's TestDiscovery
autoloads from tests/src/FunctionalJavascript
, tests/src/Functional
, tests/src/Kernel
, and tests/src/Unit
. In order to support traits anywhere in tests/src
we need to change TestDiscovery
to work the same way as PHPunit's bootstrap.php
. Once TestDiscovery
can autoload from tests/src
we have an additional issue - tests outside the 4 testsuites will be discovered. To handle this we introduce a new namespace called Traits
.
We adopt a policy where test traits belong in tests/src/Traits
, and this namespace is always autoloaded along with any of the test suite namespaces.
- PHPUnit's test runner, run-tests.sh and the Simpletest UI should all work in as similar a way as possible.
- It has to be possible to only run tests of a certain type. Lumping unit, functional and functional javascript tests together is a bad idea because they have different test infrastructure requirements.
- Users should be able to get all a module's tests to run with run-test.sh --module MODULE_NAME
- Running with run-test.sh --directory MODULE_DIRECTORY and ./vendor/bin/phpunit -c ./core/phpunit.xml.dist MODULE_DIRECTORY should result in running all the same PHPUnit based tests. (run-tests should also run the simpletest tests) These should also be the same tests when using the --module option.
- Running with ./vendor/bin/phpunit -c ./core/phpunit.xml.dist --filter MODULE_NAME should also run all the module's tests
See #198 for more discussion of the solution.
Remaining tasks
User interface changes
None.
API changes
Trait classes must be moved to the Traits
namespace.
Data model changes
None.