Get­ting Start­ed with Word­Press and Unit Testing

Publisher: TJ Fogarty

Modified: 2018-03-13

Recent­ly, I’ve begun work­ing on a project built with Word­Press. One of the require­ments involves writ­ing tests and out­putting a report.

In this post, I hope to show how I’ve set up the project to utilise PHPUnit and WP_UnitTestCase. I’ve had min­i­mal expo­sure to PHPUnit in the past, so I was delight­ed to start learn­ing more.

Hey, you might read this and know a bet­ter way! Feel free to leave a comment.

Set­up #

You’ll need an install of Word­Press. This might be an exist­ing project, or a fresh install. WP-CLI is a very handy tool for quick­ly set­ting this up, but it’ll also do many, many oth­er things for you that I won’t cov­er here e.g. export­ing a data­base, and even installing plu­g­ins.

Next up, you’ll need Com­pos­er installed. I’m using this to install PHPUnit glob­al­ly with the com­mand composer global require "phpunit/phpunit=4.7.*. You can ver­i­fy the suc­cess­ful instal­la­tion with phpunit --version in your ter­mi­nal pro­vid­ed you have Com­pos­er pack­ages added to your path. (To do this, see this use­ful post.)

With­in the root of your Word­Press project you’ll need to run svn co http://develop.svn.wordpress.org/trunk/tests/phpunit/includes/. This inte­grates with PHPUnit to make writ­ing our tests a lit­tle eas­i­er. Want to cre­ate a post? $this->factory->post->create(). Want to cre­ate 30 posts? $this->factory->post->create_many(30). This goes for posts, users, com­ments, cat­e­gories… any­thing you might need to gen­er­ate. You can browse the source to learn more about it.

This doesn’t have to be in the root of your project, but this just hap­pens to be where I’ve set up mine. You should now see an includes fold­er in your project root.

You’ll need a phpunit.xml file in your root to spec­i­fy some con­fig­u­ra­tion. It’ll tell PHPUnit which files to use for it’s tests.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit
    bootstrap="./tests/bootstrap.php"
    backupGlobals="false"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true">
    <testsuites>
        <testsuite>
            <directory prefix="test-" suffix=".php">./tests/</directory>
        </testsuite>
    </testsuites>
</phpunit>

What this is say­ing is it’s look­ing for a fold­er called tests and a file called bootstrap.php. This is what will kick it all off, and <directory prefix="test-" suffix=".php"> says that test files begin with test- and have the exten­sion of .php. So go ahead and cre­ate that tests fold­er and bootstrap.php.

For starters, here’s what your boot­strap file might look like -


require_once dirname( dirname( __FILE__ ) ) . '/includes/functions.php';

function _manually_load_environment() {
    // Add your theme
    switch_theme('your-theme');

    // Update array with plugins to include ...
    $plugins_to_active = array(
        'some-plugin/some-plugin.php',
        'another-plugin/another-plugin.php'
    );

    update_option( 'active_plugins', $plugins_to_active );
}
tests_add_filter( 'muplugins_loaded', '_manually_load_environment' );

require dirname( dirname( __FILE__ ) ) . '/includes/bootstrap.php';

What we’re doing here is set­ting up some ini­tial state for our tests. I’m set­ting the theme and the plu­g­ins that I want to be active, and that’s about it.

Now, what are we going to test on? We’ll need to cre­ate an emp­ty data­base in order to run our tests against. Cre­ate a file called wp-tests-config.php in the root of your project. It’ll con­tain infor­ma­tion regard­ing your test data­base which you’ll need to create.

<?php

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

// 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', 'test_db' );
define( 'DB_USER', 'user' );
define( 'DB_PASSWORD', 'password' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8' );
define( 'DB_COLLATE', '' );

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

define( 'WP_TESTS_DOMAIN', 'custom-domain.dev' );
define( 'WP_TESTS_EMAIL', 'test@domain.com' );
define( 'WP_TESTS_TITLE', 'Test Blog' );

define( 'WP_PHP_BINARY', 'php' );

define( 'WPLANG', '' );

No more set up, let’s start writ­ing tests!

Cre­at­ing Tests #

So now you have this tests direc­to­ry with a lone­ly bootstrap.php file sit­ting in it. Let’s give it some com­pa­ny with a sim­ple test to see if the active theme is the one we set in that boot­strap file.

Cre­ate a new file called test-active-theme.php and put in the following:

<?php

    class TestActiveTheme extends WP_UnitTestCase {
        /**
         * Test that the correct theme is active (set in bootstrap.php)
         */
        function testCorrectActiveTheme() {
            $this->assertTrue('your-theme' == wp_get_theme());
        }
    }

Have a look there and you’ll see we’re extend­ing WP_UnitTestCase. This affords us some use­ful perks in that when we run our tests it re-cre­ates the data­base for a fresh Word­Press install.


Suc­cess! In your own tests, you can access your reg­u­lar Word­Press func­tions, and your active plu­g­in classes/​functions. You might even include some Com­pos­er pack­ages to mock your data (like Fak­er).

See the PHPUnit doc­u­men­ta­tion for more infor­ma­tion on the tests you can run, and how you can export the results.

For fur­ther read­ing, have a look at the tests writ­ten for Word­Press Core.

Hap­py testing!