Unit Tests in WordPress: Installing PHPUnit

PHPunit is a unit test framework for PHP that will be used as a base for testing our PHP code under WordPress. I’ve found three guides on the web that helped me understanding how to install and configure PHPunit. It hasn’t been easy to understand the process because they use different approaches and methods, so you easily get confused.

The first important aspect to understand regarding unit tests in WordPress is that you cannot use PHPunit alone. If you try to test your code using the standard PHPunit methods they will fail most of the time. The problem is that these methods don’t run the WordPress core files, so every time you call a WordPress core function your test fails. To overcome this problem a few years ago Nikolay Bachiyski wrote a library that handled all of the tests that the WordPress core codebase uses. This library has been so much appreciated that it’s been integrated into core, and now it’s the official WordPress testing library. As a result Nikolay’s repository on Github is not updated anymore, so don’t take his Github repo as a reference. In the end, to have working unit tests under WordPress you’ll have to install the WordPress tests library on top of the PHPunit test framework.

For this guide, I suppose that I want to create unit tests for a plugin called my-plugin. That name is just for the sake of the example, I won’t publish any example testing function because the scope of this guide is to configure the testing environment, not to teach how write tests.

Useful Guides to Help You Understand PHPunit

For my first PHPunit installation I followed the instructions that I found in an article written by Ollie Armstrong. This article is well written even though it’s not for newbies but unfortunately it’s a bit dated, and it still refers to Nikolay’s Github repository for the testing library. A part from that, the guide focuses on installing the tests locally without any reference to Travis CI. My goal was to develop locally and deploy remotely, and the final configuration wasn’t good for that.

Another excellent guide that helped me understanding how unit tests work is the series of articles written by Pippin Williamson. It is very well written, and it’s an excellent read but it uses WP-CLI which works only under Linux, and I needed something that could also work under Windows.

At the end, I found an excellent guide on CodeTab which is simple to follow, and explains everything. This is what I’ve followed to accomplish my goal.

Install PHPunit Locally

Depending on your OS, the installation of PHPunit is slightly different. First of all, you need a WAMP/MAMP/LAMP installation. When I installed my virtual Ubuntu machine there wasn’t any pre-installed LAMP environment but I followed this guide and everything was up in no time. If you have Windows, you can install one of the many WAMP environments available.

For Linux, you can install PHPunit with the following commands

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

Remember to add the SUDO command if you are using Ubuntu.

Verify the installation with the following command

$ phpunit --version
PHPUnit x.y.z by Sebastian Bergmann and contributors.

For Windows you can refer to this guide to install PHPunit under Windows.

I’ve installed PHPunit under both Linux Ubuntu and Windows with the above commands and guides without any issues.

Structuring the Test Environment

Our goal is to have a testing environment that works equally well locally and remotely. We don’t want to have two different sets of configuration files because that would complicate our life. It turns out that if you structure your environment well, configuring your test library is very simple. It just involves three files.

The first thing to understand is where to install our WordPress test library. Inside our my-plugin directory we will create the directory tests where we will put all our PHP and JavaScript tests functions. We want to group the two types of test files into separate folders to avoid turning our tests directory into a mess.

This is the structure that I have decided to create:

my-plugin
|____tests
     |____js
     |____phpunit
          |____includes

We will keep all our JavaScript test files under the js folder, and the PHP test files under the phpunit folder. The directory ‘includes’ will hold the WordPress test library necessary to run our WordPress tests.

WordPress uses Subversion as version control system for its tests library. We need to clone locally the WordPress test library so that we can use it. If you use Linux you can follow this procedure to clone their directory to your local pc.

$ cd my-plugin
$ cd tests/phpunit
$ svn co https://develop.svn.wordpress.org/trunk/tests/phpunit/includes/

For Windows the situation is more complicated. I haven’t been able to find a good command line svn client for Windows, and the graphic client has been discontinued. In any case, it isn’t a big issue, we don’t want to install and use svn in our pc but just clone their directory. Since there aren’t so many files inside that directory I decided that I could copy them manually one by one in my local installation. If you know a better method that works in Windows you can leave a comment.

Configuring PHPunit

Now that we have everything that we need to run our tests, we must configure the system to use the libraries and the test files that we will put inside the phpunit folder.

The first configuration file is phpunit.xml which defines the test suite and test files. We will put this file in the top directory of our plugin.

my-plugin/phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
	bootstrap="tests/phpunit/bootstrap.php"
	backupStaticAttributes="false"
	colors="true"
	convertErrorsToExceptions="true"
	convertNoticesToExceptions="true"
	convertWarningsToExceptions="true"
	processIsolation="false"
	stopOnFailure="false"
	syntaxCheck="false"
	>
	<testsuites>
			<testsuite name="Plugin Test Suite">
					<directory prefix="test." suffix=".php">tests/phpunit/</directory>
			</testsuite>
	</testsuites>
</phpunit>

This file, among other things, tells phpunit where the bootstrap file is and how tests files are named. In this case all our tests file are located under ‘test/phpunit’, their name begins with test. and have .php extension. Any other file in the directory ‘test/phpunit’ that doesn’t have this characteristic will be ignored when it’s time to run tests.

Next, we need to configure the bootstrap file that will be used by phpunit to bootstrap the tests. We will put this file in

/my-plugin/tests/bootstrap.php

<?php
/**
 * Bootstrap the plugin unit testing environment.
 *
 * Edit 'active_plugins' setting below to point to your main plugin file.
 *
 * @package wordpress-plugin-tests
 */
// Activates this plugin in WordPress so it can be tested.

$GLOBALS['wp_tests_options'] = array(
	'active_plugins' => array(
		'my-plugin/my-plugin.php'
	),
	'wpsp_test' => true
);

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

I’ve reduced this file to the bare minimum compared to what I’ve found in the other guides. But it works, and this is what matters to me. What this file does is simply to activate the plugin in WordPress, and include the WordPress tests library.

These two files will be used also in Travis CI without any modification. They are perfect as they are, and they work in both environments.

The third file that we need is wp-tests-config.php used to create a new instance of WordPress and connect it to the database. I have chosen to put this file in the top directory of the plugin but it could also go in tests/phpunit provided that you change the ABSPATH constant.

/my-plugin/wp-tests-config.php

<?php

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

define( 'WP_DEBUG', false );

// WARNING WARNING WARNING!
// tests DROPS ALL TABLES in the database. DO NOT use a production database

define( 'DB_NAME', 'wptest' );
define( 'DB_USER', 'wptest' );
define( 'DB_PASSWORD', 'wptest' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8' );
define( 'DB_COLLATE', '' );

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

define( 'WP_TESTS_DOMAIN', 'localhost' );
define( 'WP_TESTS_EMAIL', 'admin@example.org' );
define( 'WP_TESTS_TITLE', 'Test Blog' );

define( 'WP_PHP_BINARY', 'php' );

define( 'WPLANG', '' );

/* Cron tries to make an HTTP request to the blog, which always fails, because tests are run in CLI mode only */
define( 'DISABLE_WP_CRON', true );

define( 'WP_ALLOW_MULTISITE', false );
if ( WP_ALLOW_MULTISITE ) {
	define( 'WP_TESTS_BLOGS', 'first,second,third,fourth' );
}
if ( WP_ALLOW_MULTISITE && !defined('WP_INSTALLING') ) {
	define( 'SUBDOMAIN_INSTALL', WP_TESTS_SUBDOMAIN_INSTALL );
	define( 'MULTISITE', true );
	define( 'DOMAIN_CURRENT_SITE', WP_TESTS_DOMAIN );
	define( 'PATH_CURRENT_SITE', '/' );
	define( 'SITE_ID_CURRENT_SITE', 1);
	define( 'BLOG_ID_CURRENT_SITE', 1);
	//define( 'SUNRISE', TRUE );
}

There’s an important consideration to make at this point. The unit tests libraries drop all the database tables, so you should never run unit tests in a production database. Make a testing WordPress installation in a dedicated local domain, and use it only for unit tests.

We won’t use this file in our Travis CI build because we must use a predefined DB name and credentials  without password there. The file will be created during the installation right inside Travis CI, and will overwrite our wp-tests-config.php file.

The next step object of the next article will be the installation of all the libraries for JavaScript testing. Stay tuned.

Other Articles in This Series

Unit Tests in WordPress: an Introduction

Unit Tests in WordPress: Testing JavaScript With Karma

Unit Tests in WordPress: Making It Work on Travis


So, what do you think ?