77f8e2b834
During the bootstrap of PHPUnit we ensure that the database has been reset to its initial state. We do this by checking the internally-stored DB write count between runs. If the count is not yet set (null), or it has been increased, we force a reset. When running an isolated test the test runner resets the database, it then sets up a new isolated test environment by writing a new PHPUnit test case and passing it to a new PHP Process using standard in. As part of this, the bootstrap is run for that process. Because we are in a new process, the db write count is fresh and not yet set. This has been leading to an additional db reset before the isolated test. To handle this we want to _not_ perform a reset during the initialisation for isolated runs. We know that the DB is in a fresh state before we start the run. To support this we need to know whether the test is an isolated test during the bootstrap, which means we cannot use the previous approach to calculating this. Instead we look at the PHP_SELF value. PHP sets this to "Standard input code" when run from stdin, instead of running a file. There should not be any other legitimate reason to run a PHPUnit bootstrap via this stdin approach. Unfortunately this approach is a little bit risky as it depends on the presence of a specific string, however this string has been in place since 2016, and there is no legitimate way of calculating this. I did consider looking at whether the called script included `/vendor/` and `/phpunit`, but this is also likely a risky approach if someone calls PHPUnit in an unexpected way. This approach is itself unit tested so any change to PHP's stdin string before we deprecate this approach entirely in 12 months time will be caught.
PHPUnit testing support in Moodle
Documentation
- Moodle PHPUnit integration
- Moodle Writing PHPUnit tests
- PHPUnit online documentation
- Composer dependency manager
Composer installation
Composer is a dependency manager for PHP projects. It installs PHP libraries into /vendor/ subdirectory inside your moodle dirroot.
- install Composer - http://getcomposer.org/doc/00-intro.md
- install PHUnit and dependencies - go to your Moodle dirroot and execute
php composer.phar install
Configure your server
You need to create a new dataroot directory and specify a separate database prefix for the test environment, see config-dist.php for more information.
- add
$CFG->phpunit_prefix = 'phpu_';to your config.php file - and
$CFG->phpunit_dataroot = '/path/to/phpunitdataroot';to your config.php file
Initialise the test environment
Before first execution and after every upgrade the PHPUnit test environment needs to be initialised, this command also builds the phpunit.xml configuration files.
- execute
php admin/tool/phpunit/cli/init.php
Execute tests
- execute
vendor/bin/phpunitfrom dirroot directory - you can execute a single test case class using class name followed by path to test file
vendor/bin/phpunit lib/tests/phpunit_test.php - it is also possible to create custom configuration files in xml format and use
vendor/bin/phpunit -c mytestsuites.xml
How to add more tests?
- create
tests/directory in your add-on - add test file, for example
local/mytest/tests/my_test.phpfile withmy_testclass that extendsbasic_testcaseoradvanced_testcase - set the test class namespace to that of the class being tested
- add some
test_*()methods - execute your new test case
vendor/bin/phpunit local/mytest/tests/my_test.php - execute
php admin/tool/phpunit/cli/init.phpto get the plugin tests included in main phpunit.xml configuration file
Windows support
- use
\instead of/in paths in examples above