Photo of Unit testing Islands

Unit Testing with WordPress

Unit Testing is a fantastic tool in the modern day web developer’s arsenal. The ability to run a defined group of tests every time to make a change to your code base will save you hours squashing bugs and wondering where they came from.

Unit testing has been around for a while, but most WordPress developers haven’t gotten to grips with it. At its Core, Unit testing is a way of testing how individual pieces of code (units) function. If you can test all of your units of code and be sure that they all work, you can be pretty sure that your project will be fine. Obviously, Unit testing won’t stop bugs from happening but it can help you catch them before they go to production or are released to the public.

Unit testing is particularly useful if you are building a project with many components that must interact with each other: core, plugins, and themes. Sounds just like WordPress to me.

Another advantage of Unit testing is that it forces developers and teams to better plan their code. Code must be written in such a way that individual pieces can be tested. When given a specific input, a specific output should result. This code tends to be cleaner and more reusable.

If you’re a WordPress developer and looking to incorporate unit testing into your process, you’re in luck! WordPress ships with its own testing framework.

In today’s post, we’re going to talk you through how to get Unit Testing up & running with your WordPress setup.

Getting Started With PHPUnit

PHPUnit is a testing framework for PHP applications. It allows you to define tests and run them against your code base from the command line, and is completely automatable should you want to add it to git pre hooks, or be part of a Continual Integration platform. In PHPUnit you define settings for PHPUnit in an XML file and then write your tests in PHP in a location that you specify. PHPUnit will run your tests and give you a breakdown about whether your code passes the tests.

First, let’s install PHPUnit.

Open up a terminal window and…


wget https://phar.phpunit.de/phpunit.phar
chmod +x phpunit.phar
sudo mv phpunit.phar /usr/local/bin/phpunit

This will download PHPUnit onto your computer, make the file executable by your user and copies it to your executable bin.


phpunit --version

Will return a version number so you know it works. If you don’t get that, something has gone badly wrong.


PHPUnit 4.7.0 by Sebastian Bergmann and contributors.

Let’s create a directory called wptest in the root of your local server.

If you use composer in your projects you can install it locally to your project as a dependency by adding it to your developer requirements and the running composer update

{
    "require-dev": {
        "phpunit/phpunit": "4.7.*"
    }
}

PHPunit & WordPress

WordPress’ test suite is distributed in the SVN repo but not its distribution files. If you’re checking it out from SVN you’re good to go; if you’re not you’ll have to copy it across.


svn co http://develop.svn.wordpress.org/tags/4.2.2/tests/

Will check out the tests for the latest (at the time of writing) version of WordPress, but you can swap that for whatever version you want.

WordPress uses an empty database and a different configuration file for running tests. Once cloned, we need to create a new configuration file for our tests. Create wp-tests-config.php which should look like..




/* Path to the WordPress codebase you'd like to test. Add a backslash in the end. */
define( 'ABSPATH', dirname( __FILE__ ) . '/src/' );

// Test with multisite enabled.
// Alternatively, use the tests/phpunit/multisite.xml configuration file.
// define( 'WP_TESTS_MULTISITE', true );

// Force known bugs to be run.
// Tests with an associated Trac ticket that is still open are normally skipped.
// define( 'WP_TESTS_FORCE_KNOWN_BUGS', true );

// Test with WordPress debug mode (default).
define( 'WP_DEBUG', true );

// ** MySQL settings ** //

// This configuration file will be used by the copy of WordPress being tested.
// wordpress/wp-config.php will be ignored.

// WARNING WARNING WARNING!
// These tests will DROP ALL TABLES in the database with the prefix named below.
// DO NOT use a production database or one that is shared with something else.

define( 'DB_NAME', 'youremptytestdbnamehere' );
define( 'DB_USER', 'yourusernamehere' );
define( 'DB_PASSWORD', 'yourpasswordhere' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8' );
define( 'DB_COLLATE', '' );

$table_prefix  = 'wptests_';   // Only numbers, letters, and underscores please!

define( 'WP_TESTS_DOMAIN', 'example.org' );
define( 'WP_TESTS_EMAIL', 'admin@example.org' );
define( 'WP_TESTS_TITLE', 'Test Blog' );

define( 'WP_PHP_BINARY', 'php' );

define( 'WPLANG', '' );

You can pretty much duplicate your existing database details from wp-config.php into wp-tests-config.php, however, make sure you use a separate database. WordPress will drop/recreate tables as part of the test process, so you don’t want to lose critical data from your primary database.

Within the root of your project, create phpunit.xml with the following:


<phpunit bootstrap="tests/phpunit/includes/bootstrap.php" backupGlobals="false" colors="true">
<testsuites>
<!-- Default test suite to run all tests -->
<testsuite>
<directory suffix=".php">tests/phpunit/tests</directory>
<exclude>tests/phpunit/tests/actions/closures.php</exclude>
<exclude>tests/phpunit/tests/image/editor.php</exclude>
<exclude>tests/phpunit/tests/image/editor_gd.php</exclude>
<exclude>tests/phpunit/tests/image/editor_imagick.php</exclude>
<file phpVersion="5.3.0">tests/phpunit/tests/actions/closures.php</file>
<file phpVersion="5.3.0">tests/phpunit/tests/image/editor.php</file>
<file phpVersion="5.3.0">tests/phpunit/tests/image/editor_gd.php</file>
<file phpVersion="5.3.0">tests/phpunit/tests/image/editor_imagick.php</file>
</testsuite>
</testsuites>
<groups>
<exclude>
<group>ajax</group>
<group>external-http</group>
</exclude>
</groups>
<logging>
<log type="junit" target="tests/phpunit/build/logs/junit.xml" logIncompleteSkipped="false"/>
</logging>
<php>
<const name="WP_RUN_CORE_TESTS" value="1"/>
</php>
</phpunit>

Now run the command:

phpunit

PHPUnit will now try and run the file tests/phpunit/includes/bootstrap.php to start WordPress in its testing environment. It will then load every PHP file in tests/phpunit/tests/ except those explicitly excluded in the configuration. You should see the output of the tests in your terminal window.

You have now successfully run WordPress’ test suit and can add this to your build process!

This isn’t super useful to most people. It’s great if you’re writing code to go in WordPress Core, not so much if you are trying to build a great client site.

What we want to be able to do is bring in the Unit test, not just from WordPress, but from all of our plugins, our themes as well. Then we can fully test a site and all its components together to make sure they work as expected. We’re working on making this happen, but we don’t know if we can because we’ll be depending on tests written by plugin authors. The alternative will be to run every set of tests independently, which may work, but we won’t be able to check interoperability.

Stewart Ritchie Lead developer and founder of Powered By Coffee. Stewart has been building websites for 15 years and focusing on WordPress for 5. He founded Powered By Coffee in 2011 after finishing is masters degree. He lives in Guildford Surrey with his wife Sydney and their two cats.

Signup to our mailing list