Skip to content

Instantly share code, notes, and snippets.

@stevegrunwell
Created May 10, 2021 01:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stevegrunwell/1876f7a35a2be88e80faea297cc29f94 to your computer and use it in GitHub Desktop.
Save stevegrunwell/1876f7a35a2be88e80faea297cc29f94 to your computer and use it in GitHub Desktop.
Getting PHPUnit 8 working with the WordPress core test suite

This code comes from the Nexcess Managed Applications (MAPPS) Must-Use plugin and is used to let the test suite run on PHPUnit 8 and above.

We're able to do this because our test suite takes advantage of Symfony's PHPUnit Bridge component, so we're already able to run our suite across multiple versions of PHPUnit, as the library takes care of differences like return typehints and differences in PHPUnit class names.

The (abbreviated) bootstrap.php file in this gist shows how we load the core test suite and, if we're running PHP 8.0 or above, will duplicate the stock includes/bootstrap.php file from the test suite to includes/bootstrap-phpunit8.php.

The duplicated bootstrap file is the same as the version that ships with core, minus the "Looks like you're using PHPUnit $version" error.


🤔 Want to learn more?

Check out my new talk, Considerations & Concerns for Platform Plugin Development, where I take a deep-dive into the architecture of the MU plugin that runs across every Managed WordPress/WooCommerce site on Nexcess.

<?php
/**
* PHPUnit bootstrap file.
*/
define( 'PROJECT_ROOT', dirname( __DIR__ ) );
$_tests_dir = getenv( 'WP_TESTS_DIR' ) ?: rtrim( sys_get_temp_dir(), '/\\' ) . '/wordpress-tests-lib';
$autoloader = dirname( __DIR__ ) . '/nexcess-mapps/vendor/autoload.php';
$bootstrap = $_tests_dir . '/includes/bootstrap.php';
if ( ! file_exists( $autoloader ) ) {
echo 'Composer dependencies must be installed for testing. Please run `composer install`, then try again.' . PHP_EOL;
exit( 1 );
}
if ( ! file_exists( $_tests_dir . '/includes/functions.php' ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo "Could not find {$_tests_dir}/includes/functions.php, have you run nexcess-mapps/vendor/bin/install-wp-tests.sh ?" . PHP_EOL;
exit( 1 );
}
/*
* Create a PHP 8.x-compatible bootstrap file.
*
* The core test suite's bootstrap file will check the PHPUnit version and, if it's greater than
* PHPUnit 7.x, will abort without trying to run.
*
* If we're running PHP 8.x, we need *at least* PHPUnit 8.x, and are able to do so via Symfony's
* PHPUnit Bridge.
*
* This will create a copy of the bootstrap file that removes the PHPUnit version check.
*/
$patched = $_tests_dir . '/includes/bootstrap-phpunit8.php';
$block = <<<'EOT'
$phpunit_version = tests_get_phpunit_version();
if ( version_compare( $phpunit_version, '5.4', '<' ) || version_compare( $phpunit_version, '8.0', '>=' ) ) {
printf(
"Error: Looks like you're using PHPUnit %s. WordPress requires at least PHPUnit 5.4 and is currently only compatible with PHPUnit up to 7.x.\n",
$phpunit_version
);
echo "Please use the latest PHPUnit version from the 7.x branch.\n";
exit( 1 );
}
EOT;
/*
* Create the patched version if it doesn't exist or if the original has been modified since
* the existing patched version was last modified.
*/
if ( ! file_exists( $patched ) || filemtime( $bootstrap ) > filemtime( $patched ) ) {
printf( 'Patching %s for PHPUnit 8.x+ compatibility' . PHP_EOL, $bootstrap );
$bootstrap_contents = (string) file_get_contents( $bootstrap );
file_put_contents( $patched, str_replace( $block, '', $bootstrap_contents ), LOCK_EX );
}
// Ensure the patched version gets loaded.
$bootstrap = $patched;
// Give access to tests_add_filter() function.
require_once $_tests_dir . '/includes/functions.php';
/**
* Manually load the plugin being tested.
*/
tests_add_filter( 'muplugins_loaded', function () {
if ( getenv( 'AUTOLOAD_PLUGIN' ) ) {
require dirname( dirname( __FILE__ ) ) . '/nexcess-mapps.php';
}
} );
// Start up the WP testing environment.
require $autoloader;
require $bootstrap;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment