Writing PHP Unit tests is a good practice to help developers identify the bugs and fix them in the development environment before going to production. It’s a good practice to write unit tests for your WordPress plugin as well. However, setting up a PHP Unit Test environment isn’t as easy as you’d like. These are the issues I encountered while setting up and writing PHP Unit Tests for WordPress plugins.
Issue 1 – The PHPUnit Polyfills library is a requirement
Issue 2 – Path to WordPress codebase on Windows
Issue 3 – Fatal error: Declaration of WP_UnitTestCase_Base::setUpBeforeClass() must be compatible with PHPUnit\Framework\TestCase::setUpBeforeClass(): void
Issue 4 – Could not find /tmp/wordpress-tests-lib/includes/functions.php
Issue 5 – wp scaffold plugin-tests command fails silently.
Issue 6 – Error: The following required constants are not defined: WP_TESTS_DOMAIN, WP_TESTS_EMAIL…
PHPUnit Tests Configuration For WordPress Plugins
Before writing about the issues, I’ll review the configuration/requirements.
1) Installing PHPUnit globally
composer global require phpunit/phpunit:8.*
We’re installing PHPUnit 8 dot latest. Run phpunit --version
to confirm it’s been installed.
2) Installing WP-CLI globally
I’ll assume that WP-CLI is already installed. Follow the official documentation if it isn’t installed already.
That’s all we’ll need globally.
3) Creating tests files for the plugin
From the WordPress root directory run the following command. Note that ‘wp-force-logout’ is the plugin slug. Replace it with yours.
wp scaffold plugin-tests wp-force-logout
4) Creating a WordPress instance to test against
From the plugin’s root directory run the following command. Note that wordpress_test is the database name you’ll want to create, root is the DB username, empty DB password, localhost is the DB_HOST, and 5.8 is the WordPress version we’re installing.
bin/install-wp-tests.sh wordpress_test root '' localhost 5.8
That’s all. Now when we run the command phpunit
from the plugin’s root directory. The tests should be performed for the test file tests/test-sample.php
of the plugin directory at the minimum. To write your tests, there’s documentation in WordPress handbook. You might also want to look at writing PHPUnit tests for Custom Post Types REST API endpoint.
Now into the main topic, the issues when running the command phpunit
which should actually run the tests but isn’t to be.
Issue 1
Error: The PHPUnit Polyfills library is a requirement for running the WP test suite. If you are trying to run plugin/theme integration tests, make sure the PHPUnit Polyfills library (https://github.com/Yoast/PHPUnit-Polyfills) is available and either load the autoload file of this library in your own test bootstrap before calling the WP Core test bootstrap file; or set the absolute path to the PHPUnit Polyfills library in a "WP_TESTS_PHPUNIT_POLYFILLS_PATH" constant to allow the WP Core bootstrap to load the Polyfills. If you are trying to run the WP Core tests, make sure to set the "WP_RUN_CORE_TESTS" constant to 1 and run composer install before running the tests. Once the dependencies are installed, you can run the tests using the Composer-installed version of PHPUnit or using a PHPUnit phar file, but the dependencies do need to be installed whichever way the tests are run.
Fix
PHPUnit Polyfills library is now required by WordPress tests. This is because it helps to fix the version compatibility issues we often face with WordPress. Here are more details if you’d like to check.
To fix the issue, add a PHPUnit Polyfills library in the plugin. Here’s one of the methods to add which is in composer.json
"require-dev":{
"yoast/phpunit-polyfills" : "1.0.3"
},
Enter composer update
to save the changes. Once the PHPUnit Polyfills library is available, load it. There are several methods as described in the error message above. I’ve included it in the plugin’s tests directory.
your-plugin/tests/bootstrap.php, in the first line, include this library:
require dirname( dirname( __FILE__ ) ) . '/vendor/yoast/phpunit-polyfills/phpunitpolyfills-autoload.php';
Issue 2
Warning: require_once(/tmp/wordpress/wp-includes/PHPMailer/PHPMailer.php): failed to open stream: No such file or directory in C:\Users\dell\AppData\Local\Temp\wordpress-tests-lib\includes\mock-mailer.php on line 2
Fatal error: require_once(): Failed opening required ‘/tmp/wordpress/wp-includes/PHPMailer/PHPMailer.php’ (include_path=’.;C:/laragon/etc/php/pear’) in C:\Users\dell\AppData\Local\Temp\wordpress-tests-lib\includes\mock-mailer.php on line 2
Fix
If you’re on windows, go to C:\Users\{user}\AppData\Local\Temp\wordpress-tests-lib\wp-tests-config.php
In line 4, after the comment:
/* Path to the WordPress codebase you’d like to test. Add a forward slash in the end. */
define( 'ABSPATH', '/tmp/wordpress/' );
Change the absolute path to C:\Users{User}\AppData\Local\Temp/wordpress/ or to any of your WordPress root directory. So, that it will be:
define( 'ABSPATH', 'C:\Users\{name}\AppData\Local\Temp/wordpress/' );
Issue 3
Fatal error: Declaration of WP_UnitTestCase_Base::setUpBeforeClass() must be compatible with PHPUnit\Framework\TestCase::setUpBeforeClass(): void in C:\Users\{name}\AppData\Local\Temp\wordpress-tests-lib\includes\abstract-testcase.php on line 15
Fix
This is a void
conundrum. The PHP Polyfills should also fix this issue. But, if you’re still facing issues, check the version of WordPress, PHPUnit, PHPUnit Polyfills library, etc. or this is supposed to be fixed in WordPress 5.9. Here are the changes coming in WordPress 5.9 you might want to look at.
There’s also a famous core trac.
Issue 4
Could not find /tmp/wordpress-tests-lib/includes/functions.php, have you run bin/install-wp-tests.sh ?
Fix
Delete the wordpress-tests-lib
folder from temp
. In windows, generally, it would be something like C:/Users/{name}/AppData/Local/Temp/wordpress-tests-lib.
And then re-run
bin/install-wp-tests.sh wordpress_test root '' localhost 5.8
Issue 5
wp scaffold plugin-tests command does nothing, fails silently.
Fix
This is usually because of fatal errors within your site. To find out the errors, make sure you’ve turned on the error display in wp-config.php.
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'SAVEQUERIES', true );
define( 'WP_DEBUG_DISPLAY', true );
@ini_set( 'display_errors', 1 );
define( 'SCRIPT_DEBUG', true );
Once you enabled the error display, the fatal error will display while you enter the WP-CLI command instead of failing silently.
If you get errors like undefined add_action(), undefined add_filter(), double-check your wp-config.php file, it might have been poorly customized resulting in the error.
Issue 6
Error: The following required constants are not defined: WP_TESTS_DOMAIN, WP_TESTS_EMAIL, WP_TESTS_TITLE, WP_PHP_BINARY.
Fix
It is likely that the wp-tests-config.php is missing or is empty. If you’re on windows, go to C:\Users\{user}\AppData\Local\Temp\wordpress-tests-lib\wp-tests-config.php
. If it’s missing or is empty, we’ll need to create a wp-tests-config.php
file manually. Copy the contents from here and paste them in wp-tests-config.php
. You can check your wp-config.php
file for reference.
I hope you found this tutorial helpful! Have you encountered any other issues and have a fix? Let me know.
This post was incredibly helpful. Just a note. In my case, the polyfills didn’t fix the void conundrum issues on Windows. I just needed to do add void as return type for the setUp method, replacing:
protected function setUp() {
parent::setUp();
// …
}
For this:
protected function setUp(): void {
parent::setUp();
// …
}
An the same for the tearDown methods.
The official example plugin has a wp-config.php in the tests folder, you can see that here:/
https://github.com/wp-phpunit/example-plugin/
Why is it not named wp-tests-config.php?
Not understanding what you wrote down for that error, It needs more explanation on the setup, are we supposed to create a file wp-tests-config.php and put it somewhere in the app (for example the root directory of a plugin)? And are the contents supposed to be the exact same of the wp-config.php thats in the tests folder of that example plugin?
getting issue 4 function.php missing . trying to fix as you mentioned but not working.
Thanks a lot Sanjeev! Was struggling with setting up tests. Not a lot of documentation available. And not a lot of plugins seem to have any tests haha
Hi Sanjeev,
Thanks for taking the time to share these fixes!
I was struggling with Issue 1 and your second step of including it in your-plugin/tests/bootstrap.php fixed it for me.
Thanks!
Nathan
You’re welcome. I’m glad to hear that it’s helpful.