Unit testing in WordPress

One of the things I really appreciate about developing in the .Net stack is the fantastic unit test support. Using mocking libraries like moq and leaning on the power of nunit to handle my dependencies means I can write unit tests that truly do test just the unit under test. True unit tests are useful for three very important reasons:

  1. That the code is doing what it should
  2. That the code handles unexpected inputs correctly
  3. That after refactoring the code continues to do what it did before

A robust, extensive suite of tests – both unit and integration tests – are crucial for good quality software and, fortunately, have been pretty common in the .Net development world for a long while.

When developing for WordPress, however, it’s not always been that way. I remember not so many years ago that test of any kind wasn’t something often talked about in the WordPress community. I guess we were focussed on getting code shipped.

Things have changed, and automated testing is now a recognised part of the WordPress development workflow. One of the problems with the WordPress Unit Test Suite, as pointed out by Greg Boone, is that it’s not actually a suite of unit tests – it has dependencies like a MySQL database, so would be more correctly called a suite of integrations tests. Pippin also calls these kind of tests “unit”, but they are definitely integration tests.

I’m at risk of over-egging this point, so please read this good description of the difference between unit and integration tests.

To ensure the large WordPress plugin I’m currently building is as good as it can be I want to build a suite of (true) unit tests. That means I need way of mocking WordPress functions (such as do_action, apply_filters and wp_insert_post) and globals such as $current_user and – crucially – $wpdb. It turns out there are a few options, which I’ve briefly investigated. I’ll be using WP_Mock and the PHPUnit test double features.

The well-known WP_Mock from the clever guys at 10up is the backbone of mocking WordPress. It allows you to mock any WordPress function with some simple syntax:

\WP_Mock::wpFunction( 'get_permalink', array(
            'args' => 42,
            'times' => 1,
            'return' => 'http://example.com/foo'
        ) );

This will mock the get_permalink method when the only argument is the integer 42, ensuring it is only called once, and returning the string ‘http://example.com/foo’. Clever stuff.

There are other static methods in the WP_Mock class which allow you to:

  • Mock a method which returns the same value (a pass-through method)
  • Mock the calling of filters and actions
  • Mock the setting of actions and filters

Mocking $wpdb turns out to be pretty simple, as I can use the built-in test double functionality in PHPUnit. Sample code in the MockPress project wiki shows I can do this:

// in my test setUp method:
global $wpdb;
unset($wpdb);

// whenever I want to mock a $wpdb function I set up the method to mock:
$wpdb = $this->getMock('wpdb', array('get_var'));
// and set the value I want to be returned from my mock method:
$wpdb->expects($this->once())->method('get_var')->will($this->returnValue(1);

// now I can check the mock returns what I want:
$result = $wpdb->get_var("select anything from anywhere");
$this->assertEquals(1, $result);

I now just have to ensure my code is written in such a way as to make unit testing easy! I can highly recommend The Art of Unit Testing by Roy Osherove if you want to get into this deeply.