Whether you are currently writing a WordPress plugin and have decided to embrace unit testing or you are about to begin development of a plugin and want to unit test it from the start, learning how to do it correctly is a must.
This guide assumes you have a working LAMP stack (or similar) setup on your development machine and have reasonable knowledge of databases. For easy set up of a LAMP stack see XAMMP (windows/linux) or MAMP (Mac). You should also have Git installed.
Unit Testing Overview
Unit testing is a great way to ensure that everything is working as expected. When refactoring your code base later down the line you’ll be glad you’ve written full and thorough unit tests. The basis of Test Driven Development (TDD) involves:
- Write a failing test.
- Write code so that the test passes.
- Refactor.
Hopefully you’re reasonably familiar with that process. I’m not going into the whole TDD thing here, so read around for more info. However, unit testing a WordPress plugin is a a totally different operation than a standard PHP app.
The Problem With Standard Practices
If you try to go about unit testing your plugin using the standard means that you would with any other app then you are likely going to fail. This is because these methods will not run any of the WordPress core code, therefore if you do anything like get_option() in your plugin that will instantly fail. So how do we go about this without rewriting all of your classes with duplicate methods in order to test? You also want to be testing against a clean WordPress install for every test so that any remains from failed tests will not impact the success of future tests.
Using The WordPress-Tests Library
Some clever bloke has written a fantastic library that handles all of the tests that the WordPress core codebase uses. So we are going to make use of that library in order to test our plugin. What this does is runs all of your plugin’s unit tests within a clean WordPress environment every time you run them. It makes use of the PHPUnit PEAR extension, so it’s built on strong standards that you are (hopefully) familiar with from previous PHP projects.
Getting Set Up
Firstly you need PHPUnit. The easiest way to get hold of this is using PEAR. This can be achieved by running the following commands as root.
pear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit
Once run, test everything works by running:
phpunit --version
If you are having issues then refer to the PHPUnit Installation Manual.
Now to set up your environment. You’ll need the wordpress-test framework somewhere on your development machine.
mkdir ~/src
cd ~/src
git clone https://github.com/nb/wordpress-tests.git
In the new ~/src/wordpress-tests/ folder you need to rename the unittests-config-sample.php file to unittests-config.php and open it up with your favourite editor. You should set the ABSPATH variable to the path to your development WordPress install and the DB settings to point to a database that should be used for testing. It is recommended to use a separate database for testing, if that isn’t possible then at least use a different $table_prefix.
That’s the testing framework all set up!
Using the Framework in your Plugin’s Tests
Change directories to your plugin directory and create a new file called phpunit.xml. This file is what holds the settings for the PHPUnit command. You will need the following content in that file:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="tests/bootstrap.php"
>
<testsuites>
<testsuite name="Plugin Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
</phpunit>
Without these settings, the testing framework may misbehave. You can change ‘Plugin Test Suite’ to the name of your plugin.
Now create a new directory in your plugin directory called tests. This is where all your tests will live. In this directory you need to create a new file called bootstrap.php. Every time your tests run this file will be loaded – it is responsible for loading the WordPress-Tests library. This file needs the content:
<?php
// Load the test environment
// https://github.com/nb/wordpress-tests
$path = '/home/ollie/src/wordpress-tests/bootstrap.php';
if (file_exists($path)) {
$GLOBALS['wp_tests_options'] = array(
'active_plugins' => array('plugin-name/main-plugin-file.php')
);
require_once $path;
} else {
exit("Couldn't find wordpress-tests/bootstrap.phpn");
}
Obviously you will need to change the $path variable to point to where you cloned the wordpress-tests library and the active-plugins line to reflect the name of the folder that your plugin is saved in and the main file name of the plugin.
Creating the Tests
All the setting up is done, it’s now on to creating your tests. If you have no experience with using PHPUnit then Google around for some tutorials.
In the tests folder create a new file called MyPluginTest.php. Open this up and paste the following template (changing the applicable references to ‘my-plugin’):
<?php
/**
* MyPlugin Tests
*/
class MyPluginTest extends WP_UnitTestCase {
public $plugin_slug = 'my-plugin';
public function setUp() {
parent::setUp();
$this->my_plugin = $GLOBALS['my_plugin'];
}
public function testTrueStillEqualsTrue() {
$this->assertTrue(true);
}
}
All this test will do is check that true is true. Should always pass! Save this and return to your plugin directory and run PHPUnit.
phpunit
You should see that it runs the test and passes! If you get some errors then you’ve probably got a problem with your configuration or directory structure. Try to fix it yourself but if you need any help then feel free to leave a comment and I’ll try to help.
All that’s left to do is follow the TDD paradigm and create some tests. Go have a beer – you’ve done the whole world a favour by unit testing.
This guide was inspired by this question on Stack Overflow. If you are having issues have a look there and see if that post clarifies anything for you. The WordPress Codex page on Automated Testing is also quite good.
Hi,
I’ve managed to set this up, but I have some minor comments.
1. Instead of saying you have to be root user, please add ‘sudo’ before each command, this facilitates copy-paste.
2. Clarify that the $path to bootstrap.php should refer to the wordpress-tests directory.
3. Pear can be installed with ‘sudo apt-get …’
4. For some reason, line 10 of the first unit test fails: $this->my_plugin = $GLOBALS['my_plugin'];
Thanks for the write-up. I’ll be testing.
Many thanks to Ollie for this article!
For anyone else struggling with the same problem mentioned by GUI_Junkie (piont 4):
4. For some reason, line 10 of the first unit test fails: $this->my_plugin = $GLOBALS['my_plugin'];
I think the problem lies in a bit of code missing on this blog post that is mentioned on its complement at StackOverflow: http://stackoverflow.com/a/9189535/135101
If you follow that link, you can see that they declare the class that’s under test. In the same file, after the class is declared, there is a line that puts an instance of the class into the global scope, like this:
$GLOBALS['my_plugin'] = new My_Plugin();
That will then allow the line “$this->my_plugin = $GLOBALS['my_plugin'];” to work.
Hope that helps.
Thanks for the comments. In reply to those:
1. I believe that commands shouldn’t be copy and pasted anyway, the reader of this article should carefully examine and retype the commands that are listed in order to understand the command. The target audience of this post was new developers of WordPress plugins who may not be used to the terminal environment. Although reading back over this the commands aren’t very well displayed and don’t follow the conventional prefix of ‘#’ for root and ‘$’ for regular user so I’ll tidy that up.
2. Will do.
3. I will add a link and explanation to the PEAR installation guide, as not all users will have aptitude as their package manager.
4. I’ll check this.