How to add unit testing and continuous integration to your WordPress plugin

August 2, 2013

(Quick note: WordPress.org is changing some things. I will update this post if it becomes invalid. See http://make.wordpress.org/core/2013/08/06/a-new-frontier-for-core-development/ )

Unit testing WordPress plugins is a subject that has come up quite a bit lately. Adding tests into your WordPress plugins is a great idea from a quality control  perspective. It will help ensure that your code works as expected as you change and update the code. Testing in WordPress has not always been the easiest, but with the new focus on testing in core things have drastically improved for plugin authors and I am going to show you how I have recently accomplished testing.

Overview of the process

Unit testing is not simply stepped into, there is some setup involved, but luckily it is not too difficult. Here is a quick overview of what is going to happen.

  • Install and Setup PHPUnit
  • Get a copy of the WordPress unit testing code
  • Setup your plugin

And for you more intrepid developers out there I will additionally cover using Github and Travis-CI to create automated build reports when new code is committed.

 Get rolling with PHPUnit

We will be using PHPUnit for testing our code. Before we go any further lets make sure we have PHPUnit installed and setup. I am running on Mac OS X and all commands will be relative to that operating system. Linux users should be able to run similar commands, and for Windows users consult the PHPUnit manual.

UPDATE: Ripped out the previous install steps and added this much much much easier way :).

curl -O https://phar.phpunit.de/phpunit.phar 
chmod +x phpunit.phar 
mv phpunit.phar /usr/local/bin/phpunit

Setup the WordPress Unit Testing code

When you run the unit testing code in your plugin you will need to load WordPress. This is accomplished with a customized version of WordPress that is setup specifically for unit testing. This is the same version of WordPress that is used for testing core. To get started pull the latest code from the Subversion repository with:

svn checkout http://develop.svn.wordpress.org/trunk/ wordpress-tests

This will create a new folder called wordpress-tests in the current directory that will hold all the files.

Configure WordPress database

In the wordpress-tests directory there is a wp-tests-config-sample.php file. Rename this file wp-tests-config.php. Open this file for editing and find the database credentials. Add in credentials for your database and save the file. It is very important that you setup a new database for this installation as all of the tables will be dropped when you run the PHPUnit tests.

 Create your plugin

Whew! After all those steps you can finally create your plugin! At this point there is nothing special to do, write your plugin as you normally would.

As a demo lets create a simple shortcode that lets the user know if the value is greater than 10 and less than 20.

function compare_shortcode( $atts, $content="" ) {
	if( compare_valid_range( $content ) ) {
		return "$content is in valid range";
	}
	return "$content is out of valid range";
}
add_shortcode( 'compare', 'compare_shortcode' );

function compare_valid_range( $num ) {
	return ( $num >= 10 && $num <= 20 );
}

Add the testing bits

Bryan Petty has released a great plugin template that you can use to prep your plugin for unit testing (Then I forked it 😉 ). To begin visit https://github.com/blobaugh/wordpress-plugin-tests and download the following files to the root of your plugin:

  • tests/ – Folder
  • phpunit.xml

Setup plugin details

In order for PHPUnit to properly load the plugin libraries you need to edit the file tests/bootstrap.php to contain the information on where the plugin resides. In this example the plugin is in the folder compare as the file compare.php. Update the active_plugins array with your information similar to the following:

$GLOBALS['wp_tests_options'] = array(        
     'active_plugins' => array( "compare/compare.php" ),
);

The tests

Inside the tests folder you will find the file test_wordpress_plugin_tests.php. All files with tests in them should be prefixed ‘test_’. For now we will use this file. Go ahead an open it for editing.

Inside this file you will find the following class details:

class WP_Test_WordPress_Plugin_Tests extends WP_UnitTestCase

Note that all test classes should extend WP_UnitTestCase. Each method that will be run during a test needs to be prefixed with ‘test_’. In general it is best practice to create very specific tests and use descriptive naming conventions. You should also try to avoid dynamic content. Dynamic content can make it difficult to pinpoint exact test failures.

The shortcode above checks for values between 10 and 20 inclusive as valid. All others should fail. Lets create some tests for this. Be creative with your tests and try to break the code you are testing. I am replacing the file contents with:

class WP_Test_WordPress_Plugin_Tests extends WP_UnitTestCase {

	function test_negative() {
		$this->assertTrue( !compare_valid_range( -1 ) );
	}

	function test_string() {
		$this->assertTrue( !compare_valid_range( 'Hello World' ) );
	}

	function test_15_in_range() {
		$this->assertTrue( compare_valid_range( 15 ) );
	}

	function test_high_out_of_range() {
		$this->assertTrue( !compare_valid_range( 200 ) );
	}
}

Run the tests

From the root directory of the plugin you can now run phpunit without any parameters:

phpunit

Assuming all went well you will see some output scroll past.

Running as single site... To run multisite, use -c multisite.xml
Not running ajax tests... To execute these, use --group ajax.
PHPUnit 3.7.23 by Sebastian Bergmann.

Configuration read from /Applications/XAMPP/xamppfiles/htdocs/vhosts/wordpress-tests/wordpress/wp-content/plugins/compare/phpunit.xml

....

Time: 14 ms, Memory: 33.50Mb

OK (4 tests, 4 assertions)

Notice the last line says OK. If any tests fail you will see the number here, along with output about the failure, such as file and line numbers.

 Advanced: Continuous Integration using Github and Travis-CI

Continuous Integration ( CI ) is very powerful tool that helps you track build success by running tests automatically for every code commit. Travis-CI is a good CI system that integrates well with Github. Travis-CI used to only support public projects but now also support private Github repositories. Setup is very simple and can be done in the following few steps:

  1. Setup a Github repository for the plugin
  2. Sign into Travis-CI with your Github user account
  3. From your Travis-CI profile page click the slider next to the Github repository of the plugin and make sure it says On
  4. Copy the .travis.yml file from https://github.com/blobaugh/wordpress-plugin-tests to the root of your plugin
  5. Push a new commit to Github

All done! See how easy that was? Now not only do you have local PHPUnit testing you can do before committing a plugin, you also have Travis-CI running automated tests for you ( and everyone else in your group ) and will be notified of any failures in a build.

Additional Resources

Here are some additional resources that helped me along the path to enlightenment

7 thoughts on “How to add unit testing and continuous integration to your WordPress plugin

  1. Make Sure Your Functions Function: Unit Testing — Jetpack for WordPress
  2. Alan (October 8, 2013)

    Hi Ben —
    Thanks for this article (and the one at http://jetpack.me/2013/08/20/unit-tests/ )!
    I’m reasonably competent writing phpunit tests for my php apps, but I’m new to WordPress plugins, and I’m having a tough time finding examples or advice.

    As an example, I’m writing a plug-in to add a custom post-type. From what I can tell so far, this is fairly straight-forward and everything is working as I want, but I’d like to do things right and include a test suite (even though it’s just for my personal use and I don’t have immediate plans to release it).

    But I just don’t know what to test. My custom type is in the admin menu, and the post form is just right, which is great! What do I want to test under-the-hood to confirm that automatically?

    How do I set up scaffolding to create (and destroy) some test posts, so I can test downstream functionality?

    Anyway, this is the sort of thing that I’ve been having trouble with. I suspect this is mostly a problem with my thin knowledge of the workings of WordPress, but samples for this sort of thing would be a good push for me.

  3. Get a Head Start on Unit Testing | WPSessions.com
  4. Ben Lobaugh Online » I am speaking at WordCamp Boston 2013 on Unit Testing Plugins
  5. Ben Lobaugh Online » I am speaking at WordCamp Denver 2013 on Unit Testing Plugins
  6. Ben Lobaugh Online » I am speaking at WordCamp Las Vegas 2013 on Unit Testing Plugins
  7. Temporary DB tables in WordPress PhpUnit - Incognitech