Automate WordPress Plugin Unit Testing With PHPUnit and PHP Storm

If you decide to develop WordPress plugins without the use of automated unit testing, you are setting yourself up for a great deal of wasted time over the long term.

Automated unit testing allows one to validate the quality of code, reduce the likelihood of software bugs appearing in production, and easily verifies the compatibility of new/updated code.

Download/Configure PHPUnit

a) Download appropriate PHPUnit phar file located at https://phar.phpunit.de/. Store that file in your WP project. For this demo, I am putting my phpunit.phar file in the file “/wp-content/tests/phpunit/phpunit-9.5.10.phar”.

Specify the path to that phpunit.phar file in Preferences -> PHP -> Test Frameworks -> Path to phpunit.phar. Also specify the path to the config file (phpunit.xml). See screenshot below.

configure PHPUnit settings

Setup Run/Debug Configuration

Open Run/Debug configuration panel, and click the “+” button at the top left of modal window. Select “PHPUnit”, then specify the path to the PHPUnit.xml file, preferred coverage engine (I recommend XDebug), PHP interpreter, and your plugin directory as the custom working directory. After those values have been set, they should resemble the configuration shown below:

setup run/debug configuration

At a minimum, you should enter the XML below for use in the PHPUnit.xml file. This allows you to control all PHPUnit options from a single file, such as the path to an autoload.php file, specify testsuite and code coverage options, etc.

The XML settings below will create a testsuite named “cool-plugin” (this value does not really matter), with the directory set to a plugin also named “cool-plugin” which we are testing.

<phpunit bootstrap="autoload.php" cacheResult="false" stopOnFailure="true" failOnRisky="true" colors="true">

    <testsuites>

        <testsuite name="cool-plugin">
            <directory>../../plugins/cool-plugin/tests</directory>
        </testsuite>

    </testsuites>

</phpunit>

Autoload WordPress

include_once '/absolute/file/path/WordPress/wp-load.php';

if ( WP_ADMIN ) {
	include_once ABSPATH . 'wp-admin/includes/admin.php';
}

If you run the unit tests only with the above information specified, you will receive an error stating “Test framework quit unexpectedly”. This is because WordPress is required to be loaded before PHPUnit tests are run! At a minimum, I recommend the code below be included, which will allow WordPress to be loaded properly:

If you would like more fine-tuned control over the WordPress environment which PHPUnit loads, you could use the code below to indicate you want to test code which relies on the admin panel, and you could tell PHPUnit to mimic a user which I creatively called “phpUnitTesting”. This allows the unit code to be executed in the context of a pre-determined user, whom has roles you may define (Administrator, User, Editor, etc.)

define( 'WP_ADMIN', true );

// $_SERVER['REQUEST_URI'] = '/wp-admin/admin.php?page=cool-plugin';
// $_SERVER['HTTP_HOST'] = 'localhost';

if ( WP_ADMIN ) {
	$_SERVER['PHP_SELF'] = '~/WordPress/wp-admin/admin.php';
}

include_once '~/WordPress/wp-load.php';

wp_set_current_user(2, 'phpUnitTesting' );

if ( WP_ADMIN ) {
	include_once ABSPATH . 'wp-admin/includes/admin.php';
}

Creating Unit Tests

The zip file below contains a demo plugin which has unit tests validating a WordPress plugin’s code:

/wp-content/misc/cool-plugin.zip

Conclusion

Implementing automated unit tests will greatly improve the quality of your plugins, decrease the time it takes to implement new features, reduce the time required for manual testing, and will make your users happier!