Writing Stupid Simple Unit Tests

In this post, we'll cover the basics of unit tests and walk through the process determining what types of tests you should write for your code. We'll also write a few tests to show just how simple most unit tests are.

The aim here is to make tests a bit more familiar and less daunting and mysterious. Unit tests are good. I'm by no means an expert on software testing. I'm just someone that's discovered the joy and freedom that writing tests provides.

If you are an expert on software testing and notice I'm wrong, please tell me!


What are unit tests?

If you’re not familiar with unit tests, they’re essentially software written to test discrete units of functionality in a system.

Unit tests test the expected behavior of your software as it exists (or existed) at a specific point in time. They make sure that everything works as expected based on the rules established for the software at the time it was written.

If those rules change -- and your software along with them -- your tests will fail. When they fail, you'll gain insight into how the change affects the rest of the system.

For example, if a change is made in code for your site’s user profile management, you'll want to make sure that the change does not affect the behavior of your site’s payment processing code.

Tests can save time and money by acting as the first line of defense in catching problems before they result in a late night emergency or catastrophic failure. When things go wrong, they can also serve as the first response team. You can run your unit tests to see if any rules/expectations have been broken by some recent change, either in your code or some external API dependency, and fix the bug introduced by the change.

Sometimes the tests become outdated. Again, the tests will fail, letting you know that you’re no longer testing for the right thing. When this happens, you should update your tests to make sure they are in line with the new rules for your software.

Getting started

Unit tests are rarely difficult to write or run if you’re using a testing framework (e.g., phpunit).

You can write your tests before you write your business code if Test-driven Development (TDD) is your thing or you can write them after.

It doesn’t matter much when you write them as long as you have them.

The brilliant thing is that almost all tests you write will be stupid simple.

Tests usually assert some condition is true (or false, depending on what outcome you expect).

On top of that, most testing frameworks have convenience functions built in for performing these types of tests and several others, including testing the expected output of a function (i.e., what the function prints to the screen).

The three test functions we've used most frequently when writing tests for Largo are assertEquals, assertTrue and expectOutputString.

Our stupid simple example plugin

So, let’s say that we want to write tests for a WordPress plugin. Our plugin simply prints the message “Hello world!” in the top corner of the WordPress dashboard (sound familiar?).

This is the extent of the code:

 * @package Hello_World
 * @version 0.1
 * Plugin Name: Hello World!
 * Plugin URI: https://gist.github.com/rnagle/d561bd58504a644e9657
 * Description: Just a simple WordPress plugin that prints "Hello world!" in the top corner of the WordPress dashboard.
 * Author: Ryan Nagle
 * Version: 0.1

function hello_world() {
  return "Hello world!";

function hello_world_markup() {
	echo "<p id='hello-world'>" . hello_world() . "</p>";
add_action('admin_notices', 'hello_world_markup');

function hello_world_css() {
	$x = is_rtl() ? 'left' : 'right';

	echo "
	<style type='text/css'>
	#hello-world {
		float: $x;
		padding-$x: 15px;
		padding-top: 5px;
		margin: 0;
		font-size: 11px;
add_action('admin_head', 'hello_world_css');

Couple of things to note:

  1. We have one function -- hello_world -- that returns a string.
  2. Two other functions -- hello_world_markup and hello_world_css -- that echo strings but have no return statements. This means we'll have to check the output of these functions rather than the return value to properly test them.
  3. Note that hello_world_markup relies on hello_world to provide the the “Hello world!” message.

So, how do we test this plugin? Well, if you don’t have your test framework installed and configured, you’ll want to get that ready and raring. The details are beyond the scope of what we'll cover here, but for an overview of setting up unit tests for WordPress plugins and themes, see Will Haynes’ Unit Testing Themes and Plugins in WordPress.

The INN Nerds also have a collection of deploy tools to make developing WordPress sites and writing tests much easier. You can read about using the deploy tools for testing themes and plugins here: Updates to INN’s Deploy Tools.

Disclaimer: getting unit tests working WordPress can be daunting at first. It’s a lot to digest and may take some time to set up if you’re coming to this cold, so be patient. It’ll be worth it.

If you’re really dedicated to the cause and need a hand, reach out to us.

How do I write a unit test?

With that out of the way, let’s design some unit tests for our “Hello World!” plugin.

The first thing we’ll want to do is enumerate the features of the code which we need to test.

There are many ways you can approach this. My preference is to create a single test file per file in my source code and have my tests directory mirror the structure of my source directory.

Each test file has tests for each function (or member functions of classes) in the corresponding source file.

So, the directory structure for our plugin would look like:


We’ll be doing our work in test-hello-world.php where we’ll set up the skeleton of our test case, which is as simple as extending WP_UnitTestCase:


class HelloWorldTest extends WP_UnitTestCase {}

We can then stub out test functions for each function:

 class HelloWorldTest extends WP_UnitTestCase {
  function test_hello_world() {
    // Test hello_world()

  function test_hello_world_markup() {
    // Test hello_world_markup()

  function test_hello_world_css() {
    // Test hello_world_css()

Now, let's look at each function and consider what we're testing:

1. For hello_world, we want to verify that the string returned is "Hello World!":

function test_hello_world() {
  $this->assertEquals("Hello World!" == hello_world());

Easy enough. Now if for some reason someone changes the return value to "Hello world!" -- capitalization be damned -- the test will fail.

I can hear you now, "This is stupid, no one writes code like this." Yes, the example is stupid and that's the point. Don't get caught up focusing on the wrong thing.

It makes no difference how complex the function is, the only concern is verifying that the return value or the outcome is what is expected.

So, if instead you're testing some_made_up_function which returns an object, you may want to verify that it is actually a PHP Object:

$this->assertEquals(gettype(some_made_up_function()), "object");

Or that the object has a specific member attribute:

$test_obj = some_made_up_function();
$this->assertTrue(property_exists($test_obj, 'name_of_attribute_goes_here'));

2. For hello_world_markup, we want to verify that the function prints "<p id='hello-world'>Hello World!</p>":

function test_hello_world_markup() {
  $this->expectOutputString("<p id='hello-world'>Hello World!</p>");

Notice that we're expecting "Hello World!" to be part of the output. This might not be a good thing. If the return value of hello_world changes, this test will fail, too.

For the sake of example, let's say we only care about testing the markup and not the message. We can take this test a step further and decouple the two so that we're only testing the markup by changing it to read:

function test_hello_world_markup() {
  $result = ob_get_contents();

  $this->assertTrue(!empty(preg_match("/^<p\s+id='hello-world'>.*<\/p>$/", $result)));

Essentially what we're saying is, we don't care what the message is as long as it is wrapped in <p id="hello-world" /> tag.

Simple, right?

3. For hello_world_css, we want to verify that the function prints the CSS rules for our "Hello World!" markup:

function test_hello_world_css() {
  $result = ob_get_contents();

  // Make sure there are style tags being printed. Duh.
  $this->assertTrue(!empty(preg_match("/.*?.*<\/style>/s", $result)));

  // Make sure we're using the right selector
  $this->assertTrue((bool) strpos('#hello-world', $result)));

And with that, we're done! You can see the entirety of test-hello-world.php here.

When to write tests

As mentioned earlier, you may want to write your tests first. This is called Test-driven Development.

Writing your tests first has lots of awesome benefits. When you write tests first you are forced to think about the design of your system and how best to structure the software so that it is actually testable. It’s a good practice and will help increase the orthogonality of your code.

However, it's never too late to start writing tests. When you write tests for existing code, you'll find places where things need to be refactored (sometimes completely rewritten or redesigned) to clean up the spaghetti code.

If you really can't afford the time it takes to write tests for all your code (or aren't being allotted the time to do so), you might still be able to lobby for time.

It's extremely important that you can verify your code works, especially in cases where you're using code to make an assertion about the world. For example, if you're writing code that processes a data set which will later be used in a story or investigation, it's crucial that your code produces results that are precise and correct.

The other case where you should absolutely be writing tests is for critical customer interactions. Saving sensitive information or processing payment information are things that you don't want to get wrong.

Unit Testing Themes and Plugins in WordPress


Over the past few weeks, we’ve been investigating the best way to incorporate a WordPress testing framework into our development process. With few developers out there writing tests for their plugins (and even fewer testing themes), we want to share our tribulations as we figure the process out.

Fortunately, WordPress ships and supports a unit testing framework. Unfortunately, this framework is designed mainly for development on WordPress core and not directly for WordPress plugin and theme developers. However, with enough prodding, it is possible to write your own tests on top of this library.

Step one: Installing PHPUnit

The PHPUnit library provides a base framework for writing tests in PHP. WordPress develops its own testing platform on top of this library.

Assuming you’re on a *nix system, installing PHPUnit is as simple as:

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

See the PHPUnit installation notes for installing the framework on Windows or including it with composer.

Step two: Pull in the WordPress framework

Before we go any further, I should note that wp-cli ships with a handy command that does a lot of this grunt work for you. However, it currently supports tests for plugins only (not themes). If that’s all you need, it’s the fastest way to get started, but the steps below should give you a better understanding of what’s happening behind the scenes and give you a setup that can be customized for your specific development environment.

WordPress bundles its testing framework in with its core development tools svn repo. We can download just the tools we want by checking out the includes directory. It’s up to you where you want to organize your testing library. For the sake of this tutorial, we’ll assume you clone it into your root WordPress directory.

cd <wproot>
svn co http://develop.svn.wordpress.org/trunk/tests/phpunit/includes/

You’ll need a second WordPress config file named wp-tests-config.php as defined here:


Configure the database details as you would a normal wp-config.php. It’s important to use a secondary database, as WordPress drops and recreates tables as part of its tests. In addition, ensure that ABSPATH is pointed to the correct WordPress install to use during testing.

Step three: Hook it all together

What we do now is create a phpunit.xml file. This file is what PHPUnit uses to load the testing environment and run its tests. It doesn’t matter where you create this file, but for the sake of this tutorial we’ll add it to the WordPress root directory (the same place we downloaded the WordPress test framework).

			<directory prefix="test-" suffix=".php">./tests/</directory>

Now, if you run PHPUnit from the command line —

cd <wproot>

— you should see this on the command line.


If errors are thrown, check that your paths all point to the correct place.

Step four: Building tests

What we’ve got so far is the included framework that ships with WordPress. First, our phpunit.xml file is specifying a bootstrap.php file to load and install WordPress. Then, it's looking in ./tests/ for files in the format test-*.php to run actual tests. Since we don’t have any tests yet, no tests are executed.

This base configuration is only running tests on WordPress core functions. In order to test our own plugin and theme functions, we must create our own bootstrap.php file to specify which theme and plugins to activate before installing WordPress. Create a new file called ./tests/bootstrap.php. In this file, include the following:


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

function _manually_load_environment() {
	// Add your theme …
	// Update array with plugins to include ...
	$plugins_to_active = array(

	update_option( 'active_plugins', $plugins_to_active );

tests_add_filter( 'muplugins_loaded', '_manually_load_environment' );

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

Update your phpunit.xml file to include this new bootstrap file, instead of the WordPress default.

Now you have everything you need to write unit tests on your theme. Create a new file named ./tests/test-sample.php and write your first test:

class SampleTest extends WP_UnitTestCase {
	function testSample() {
		$this->assertTrue( 'Your Theme' == wp_get_theme() );
		$this->assertTrue( is_plugin_active('your-plugin/your-plugin.php') );

Running phpunit now, you should see the following:


That’s it! You’re now able to write your own test functions to test your code.

Final words

It’s important to note that while this is one way to organize your testing code, it might not be the best for your development environment. You might, for example, prefer to keep your test suite (./tests/) in the root of a theme or plugin directory, so that it is included in version control. Or you might want to keep tests completely outside of the WordPress directory.

Diving deeper, you might want to activate and deactivate plugins directly in the testing classes to test what happens when plugins aren’t loaded. You might want to maintain multiple test suites for different plugins or themes.

Lastly, now that you are set up to write unit tests, you might be asking how you should go about writing a test. We’ll cover some unit testing best practices over the coming weeks as we write our own tests for our codebase. For now, take a look at some test classes that WordPress has written to get a feel for how tests are built.