Advanced OOP For WordPress Part 2: Setting Up Automated Testing Of WordPress REST API Plugins

In my last post, I showed how to modify the WordPress content endpoints using WordPress hooks — aka the WordPress plugins API — during REST API requests. The practical example changed the underlying query to improve search.

Now I need to test that code isolated from the WordPress plugins API. For this article, we will assume the Plugins API is working as documented. This, however, isn’t a safe assumption, so we need to be ready if it isn’t working as planned.

This post is really about how we can control for that problem. I’ll be walking you through setting up a WordPress plugin for acceptance testing and unit testing, and explaining what we can and can’t test with unit tests. Doing so should help you understand how to structure your code with this distinction in mind and begin to show you the tools and techniques of writing these two distinct kinds of tests.

Setting Up A WordPress Plugin For Unit & Integration Tests

Using WP-CLI To Create A WordPress Plugin With Unit Tests

I don’t want to spend a ton of time on how to setup and structure the plugin and tests. We can use WP-CLI to scaffold most of the code for us. So first, let’s create the plugin using this command.

wp scaffold plugin rest-api-search

This creates a plugin called “rest-api-search” with the WordPress test suite ready to go. This is great, because we’ll want to use that for integration tests. I’d rather use PHPUnit directly for my unit tests. Also, I’d like to manage running tests and sniffs using Composer and have Composer to provide a PSR-4 autoloader.

You can learn more about how I set this up by reading these posts from Torque:

I did make two big changes to what WP-CLI created. First, I changed the PHPCS ruleset to use tabs instead of spaces in order to follow the PSR2 instead of the WordPress coding standard.

Previously I had used inline arguments for the code sniffer. Now I am using a PHPCS XML configuration file as command line options would be too complex:

<?xml version="1.0"?>
<!--Largely Sourced Form https://gist.github.com/gsherwood/9d22f634c57f990a7c64-->
<ruleset name="CalderaLearn">
    <description>PSR2 with tabs instead of spaces.</description>
    <arg name="tab-width" value="4"/>
    <rule ref="PSR2">
        <exclude name="Generic.WhiteSpace.DisallowTabIndent"/>
    </rule>
    <rule ref="Generic.WhiteSpace.DisallowSpaceIndent"/>
    <rule ref="Generic.WhiteSpace.ScopeIndent">
        <properties>
            <property name="indent" value="4"/>
            <property name="tabIndent" value="true"/>
        </properties>
    </rule>
    <!-- The soft limit on line length MUST be 120 characters; automated style checkers MUST warn but MUST NOT error at the soft limit. -->
     <rule ref="Generic.Files.LineLength">
      <properties>
       <property name="lineLimit" value="120"/>
       <property name="absoluteLineLimit" value="0"/>
      </properties>
     </rule>
</rulese

This imports the PSR-2 standard and adds one modification. To quickly confirm my code to this new standard, I used the command phpcbf, which is a part of PHPCS, to fix all of my code to the new standard. I changed the “fixes” command from the previous article to use PHPCS’ built-in fixer since it will automatically use that same xml configuration file. Here is the new command:

phpcbf src/ && phpcbf tests/

Second, I restructured the tests so that they were in two suites: unit and integration. Later on an acceptance testing suite may get added, but for now, that’s what we need. Since I’m going to use Composer’s autoloader for tests, I organized the directories and class names according to the PSR-4 spec.

As a result, the directory for my unit test is Tests/Unit and the directory for my testing mocks is Tests/Mocks. I moved the tests WP CLI generated into their own directory and bootstrap folder that are not being used. Here is what my directory structure ended up looking like before I started adding my code in:

The directory src will house my root namespace and all of my PHP classes. Here is the composer.json that pulls this all together:

View the code on Gist.

Running Tests On Git Hooks

One other new thing you might have noticed was that I added cghooks — composer git hooks. This package is a Composer plugin that hooks into Git events, and lets you run Composer scripts at those events.

I used the pre-commit hook, which fires when you make a Git commit, before it is recorded. Because this script has to exit successfully for the commit to be completed, the setup is enforcing a set of standard, required pre-commit steps.

In my case, I only added the code formatting, not the tests. This prevents code formatting issues from getting pushed uupstream. But it still allows incomplete work to be pushed before it fixes all of the tests.

I am hesitant to recommend using this on a community open-source project as not all developers may want to or need to install the tests to contribute.

Preparing For Unit Tests

We’re going to have to do a little refactoring before we can really get into testing. But first, I’d like to pause and write one test first.

Let’s create a super basic test that doesn’t cover any of our code. I like to add this type of test first, just to make sure my plugin test are set up correctly. It’s just asserting true is true. Effectively, it covers that PHPUnit works for in this context.

<?php
namespace CalderaLearnRestSearchTestsUnit;
/**
 * Class ExampleTest
 *
 * An example unit test
 *
 * @package CalderaLearnRestSearchTestsUnit
 */
class ExampleTest extends TestCase
{
	/**
	 * Super basic test for educational purposes
	 *
	 * @covers TestCase
	 */
	public function testTheTruth()
	{
		//What should the value be?
		$excepted = true;
		//What is the value actually
		$actual = false;
		//Are they not the same?
		$this->assertNotEquals($excepted, $actual);
	}
}

When we’re writing unit tests, our goal is to test our own systems with as few dependencies as possible. No dependencies is the impossible ideal we strive for. We’ll trust that PHPUnit’s tests work, as long as that one test passes we can trust that dependency.

You may notice that this test is extending a class in the same namespace called TestCase. That’s just an empty class extending PHPUnitFrameworkTestCase. The recommended file structure for phpunit tests is one class of tests per class. So we’re going to have several classes in our tests directory. I guarantee you at some point we’ll want to share code between these tests. Having all of our test classes extending one class is going to help a lot.

<?php
namespace CalderaLearnRestSearchTestsUnit;
//Import PHP unit test case.
//Must be aliased to avoid having two classes of same name in scope.
use PHPUnitFrameworkTestCase as FrameworkTestCase;
/**
 * Class TestCase
 *
 * Default test case for all unit tests
 * @package CalderaLearnRestSearchTestsUnit
 */
abstract class TestCase extends FrameworkTestCase
{
	//We'll put shared code for all tests here later
}

Time To Start Testing

If that test passes, then you have your test suite setup. That’s awesome. Now you can start writing tests on your own, or wait until the next post were we’ll cover refactoring the code for testability and writing more tests.

The plugin I’ve been using to create and test this example code can be found on Github. It needs more tests to achieve full coverage. Feel free to fork it and learn more by experimenting with it.

Before we wrap up, I’d like to come back briefly to the automatically generated same test that WP-CLI generated and it’s install script. WordPress’ test suite, which we’ll get back to, is not going to be run with composer like the rest of our tests are.

It is common in the WordPress ecosystem to use that test suite for unit tests and integration tests. I’m not fond of that pattern, as I want to treat them as two totally different test suites and I like using Composer for scripting all of this. I’ll be covering why over my next two posts, but I want to point that out if you’re used to using them together.

Josh is a WordPress developer and educator. He is the founder of Caldera Labs, makers of awesome WordPress tools including Caldera Forms — a drag and drop, responsive WordPress form builder. He teaches WordPress development at Caldera Learn.

The post Advanced OOP For WordPress Part 2: Setting Up Automated Testing Of WordPress REST API Plugins appeared first on Torque.