PHP Unit Testing and Pad Thai

As a follow-up to my last post about PHP unit testing, I recently gave a talk at WordCamp Boston about how to write testable WordPress plugins. You can see the talk slides here:

You can also watch the talk here, although the audio quality isn’t great.

The premise of my talk was mainly that having testable code is a really great idea, even (and perhaps this is surprising) if there are no actual tests. Of course, without writing tests it’s hard to know for sure, but some experience will go a long way for future projects.

Even though this was at a WordCamp, my talk is not really WordPress specific. It really applies to any unit testing in PHP. In it, I gave an analogy to help my audience understand some of the concepts. Here’s that analogy:

Why have tests?

If you asked a friend to make you Pad Thai, you’ll probably get something edible, but maybe your friend isn’t such a good cook. If you don’t like the food, how can you tell what went wrong?


Defining your dependencies is important. “I want Pad Thai” vs. “I want Pad Thai, made with the following ingredients” will help. Even better, “I want Pad Thai, made with the following ingredients, ordered from this store, using this recipe”.

Mocks (AKA Stubs)

Using mocks is like asking the store to only sell your friend a particular brand of noodles when he calls. If the dish still tastes bad, you know it wasn’t because he got the wrong noodles.

What is a Spy?

Using spies is like giving your friend your phone number instead of the store’s phone number so that when he calls the store to order noodles, he calls you instead. That way you can verify that he’s ordering the right thing. If he calls and orders wheat noodles instead of rice noodles, you’ve found a bug with your friend’s recipe.

I also wrote Payton’s Testable Precepts: 10 guidelines I use when writing code that help make my code testable (as well as more clean, more flexible, and more readable). Here’s a list of those Precepts. See the slides for reasons and examples.

  1. Always use classes, never global functions.
  2. Don’t use static functions except as factories.
  3. Use instance variables as constants.
  4. Use filters to pass data indirectly.
  5. Use verbs in all function names.
  6. Keep functions below eight lines and indentation below four levels.
  7. Consider all possible inputs and outputs.
  8. Whenever possible, write tests first.
  9. Don’t test the code from other libraries, but test the inputs and outputs.
  10. Write only one assertion per test.



Test spies in PHP

I think that I wrote my first unit tests in Ruby with RSpec, back in the day. But I learned most of my testing knowledge from working with mocha and chai in JavaScript. One of the things that I learned from these tools is that being able to express your test logic in clear, nearly-natural language brings a real comfort to the often complicated life of the test-writer.

For example, here’s a line straight from the chai home page:


It’s so lovely.

When writing tests to follow the flow of code from one module to the next, it’s often useful to have Test Spies around to “spy” on the code and tell you what’s happening when. To borrow the definition from my favorite test spy library, sinon:

A test spy is a function that records arguments, return value, the value of this and exception thrown (if any) for all its calls. A test spy can be an anonymous function or it can wrap an existing function.

When brought together with sinon-chai, this allows for very expressive syntax:


Because I work a lot with WordPress, I also write a lot of unit tests in PHP. There, the defacto standard is PHPUnit, which has… less natural language. That’s fine, though, its assertions are usually perfectly readable. What it seems to be lacking, for me anyway, is Spies.

Certainly there are some great ways to use PHPUnit’s built-in mocking tools, like this (hidden) behavior, but Spies are hardly a first-class citizen. And besides, even writing this feels confusing to me:

$target = $this->getMock('TargetClass');
$target->expects($spy = $this->any())->method('doSomething');


$invocations = $spy->getInvocations();

$this->assertEquals(2, count($invocations));

I would much rather write:

$target = mock_object_for('TargetClass');
$spy = $target->spy_on_method('doSomething');



So I ended up writing a Test Spy library for PHP. I call it Spies. My intent was to have an easy and readable way to create Test Spies, Stubs, and Mocks, and also a clear way to write expectations for them.

Creating a Spy is as simple as calling \Spies\make_spy(); (although there’s many other ways to create them). You can then call the spy and ask it questions, like this:

$spy = \Spies\make_spy();
$spy( 'hello', 'world' );

$spy->was_called(); // Returns true
$spy->was_called_times( 1 ); // Returns true
$spy->was_called_times( 2 ); // Returns false
$spy->get_times_called(); // Returns 1
$spy->was_called_with( 'hello', 'world' ); // Returns true
$spy->was_called_with( 'goodbye', 'world' ); // Returns false
$spy->get_call( 0 )->get_args(); // Returns ['hello', 'world']

Here’s a more complete example of using Spies to mock an object and test its behavior:

You can install Spies using Composer by typing composer require sirbrillig/spies in your project.

I owe quite a lot to the great library WP_Mock by 10up. Many of the concepts in Spies were inspired directly by the way that WP_Mock works, like creating global functions. WP_Mock serves a slightly different purpose, though. It’s a layer on top of Mockery, which in turn is a layer on top of PHP’s own testing tools. Also, it mocks a few things by default, like filters and actions.

Spies is intended to be more generally useful, and also to make the distinction between mocking and setting expectations more clear by breaking away from PHP’s built-in mocking concepts.

I welcome comments and suggestions at the Github page! As always, I hope it ends up being useful to other people.

Copying files… sometimes

File this one under “tools that probably only I will find useful”. In the course of my normal job I need to copy files to a synchronized directory on my computer (something like a DropBox folder). The files are JavaScript code that’s been transpiled and copying them to the synchronized directory is what deploys them to my staging server.

Therefore, as I work, I need to: Code → Transpile → Deploy → Test → Repeat. My ideal work cycle is more like: Code → Test → Repeat. I want to be able to just write code and then reload my browser, not all that boring stuff in the middle.

The process of transpiling my code can be handled by a watcher (usually grunt-watch or watchify) so I don’t have to worry about that part. Unfortunately because of the deploy step my process still looks like: Code → Deploy → Test → Repeat. (Grumble grumble inefficient grumble.)

Now, one way I could handle this is just to move my whole project into the synchronized directory. That way the transpiled files are already in the right place and I don’t need a deploy step. That feels like cheating to me, though. It means that my project directory has to exactly mirror the deploy directory and it means that all of my working files are also being synchronized as I code; that’s a lot of unnecessary data over the wire.

Naturally I decided to automate my way out of this problem. I thought to myself: I could just add another task so that the watcher copies my transpiled code to the synchronized directory when it’s done! Ah, but I’d need to give it an absolute path, and several developers work on this project, each with different synchronized directories. That’s not ideal. And even worse is that another developer might want to handle the deploy process differently.

This led me to write copytotheplace. It’s a very simple library and command-line tool that will allow copying files to a directory by setting the destination as an environment variable or using a config file (or a command-line option or parameter if you’re using the library directly).

If no destination directory is set, this tool will do nothing, which allows it to be used as the last step in a build pipeline without doing anything unless specifically called-for.

To hook it into my particular build tool and watcher, I wrote grunt-copytotheplace which just loads the library into a Grunt task.

Now I just put COPYTOTHEPLACE=/path/to/my/sync/directory in the .env file in my local project directory and Grunt will copy the files there every time they change. More importantly, when other developers who don’t have that option set run their version of Grunt, nothing will be copied anywhere.

I know, it’s a weird solution to a weird problem, but it was a simple way to dramatically speed up my workflow without harming others, and so for now I consider it a win. Maybe next week I’ll come up with a better way. But in the mean time, if you find this tool useful it’s up there in the cloud for all to share. Just npm install copytotheplace and away you go! (See details in the README.)

Avoiding Tightly-Coupled REST APIs

As you might have read, WordPress is getting a powerful REST API. For a few years now I’ve been writing endpoints for the version of this API, as well as few REST APIs in other languages (Ruby, JavaScript). As I’m also a big fan of unit testing, I’d like to share a pattern that I’ve learned from trial and error.

To make REST API endpoints more testable, as well as more useful, write the logic in a separate library.

Let’s say I have an endpoint that updates a menu item on a restaurant web site. In WordPress I have the menu item set up as a custom post type (you don’t need to grok WordPress to benefit from this pattern, but I thought I’d mention it).

The basic operation of the endpoint is this:

  1. Take the post ID and the new field values from the data submitted to the endpoint.
  2. Find the matching post in the database.
  3. Verify user permissions to update that post.
  4. Calculate the menu item’s total price based on current tax rate and ingredients.
  5. Update the post’s data.
  6. Return the newly updated post data to the client.

I’d also like to write unit tests for each of the above operations.

Now, the first step in writing my endpoint would be to map the HTTP route to the route handler. That is, I need to map the route PUT /menu/item to a function which kicks off the process above and eventually returns the result to the client.

I could write all of the above logic right in that function. There’s even a few pieces which could be their own separate functions. But this way may not be ideal, as I’ll explain.

The route handler, wherever it might be defined, is aware that it’s part of a REST API. The exact details of that vary depending on which language, architecture, etc, that you are using. But generally the initial route handler is not just doing the work of the steps above, but also interacting in some way with the API. Perhaps it’s checking details of the path, query string, user token, or it’s sending back an HTTP-specific response.

Here’s where we can get into trouble. Let’s say later on we decide to write another REST API endpoint that accepts a new tax rate and updates all the menu items. It needs to do the following:

  1. Take the new tax rate from the submitted data.
  2. Iterate over each menu item post.
  3. Validate user permissions to update each post.
  4. Calculate each menu item’s new total price.
  5. Update each post.

Notice that steps 3, 4, and 5 are the same as the previous endpoint we made. Rather than re-write them here, let’s keep things DRY and just call the other endpoint; thus our new update-the-tax-rate endpoint looks more like this:

  1. Take the new tax rate from the submitted data.
  2. Iterate over each menu item post.
  3. Call the update-menu-item endpoint.

Ah… but in the WordPress REST API, as well as many other API frameworks in different languages, you can’t call an API endpoint from within another API endpoint. And it might be said that, even if you could, doing so adds unnecessary overhead.

In this case, if the process of finding, validating, and updating a post was all one function call in a library, maybe update_menu_item(), then this endpoint becomes so much easier. Both the update-menu-item endpoint and the update-the-tax-rate endpoint can just call update_menu_item().

Even better, so can our unit tests! While it’s a good idea to write tests for an API endpoint that actually call the API, doing so can sometimes be problematic. Unit tests usually try to test one specific behavior, separating that behavior from the rest of the system. If you test a REST API, the system being tested is on a separate server (even if the server is local to your computer), and is thus much more complicated to control. But if the API’s route handler simply calls a function in a library, we can just test that function, providing mock data and checking the results, all without even considering HTTP.

Certainly this isn’t a rule, as most rules in programming tend not to fit real-life situations. It’s just a pattern I’ve decided works well for me. I suggest you examine your own code to see if it might work for you too!

get_deep_value in PHP

Ever have an array in PHP that looks like this?

$data = [ 'one' => [ 'two' => [ 'four' => 'bar', 'three' => 'foo' ] ] ];

It can be annoying to pull deep values from such an array because if you access an array key that doesn’t exist, PHP will throw an exception.

do_something_with( $data['one']['two']['six'] ); // throws an exception!

You could check each level of the data using array_key_exists() like this:

if ( array_key_exists( 'one', $data )  && array_key_exists( 'two', $data['one'] ) && array_key_exists( 'three', $data['one']['two'] ) ) {
  do_something_with( $data['one']['two']['three'] );

But that would take forever. PHP’s isset() method fortunately makes this somewhat more clean:

if ( isset( $data['one']['two']['three'] ) ) {
  do_something_with( $data['one']['two']['three'] ); 

But that’s still a lot to type, especially if you have to do it several times. In JavaScript-land we have some nice patterns around this sort of thing. Underscores and Lodash have the _.get() method, so I’ve re-created that in PHP here as get_deep_value().

The first argument is the array you want to search, and the second argument is an array of keys, one per level.

Now you can just write:

if ( $value = Get_Deep_Value::get_deep_value( $data, ['one', 'two', 'three'] ) {
  do_something_with( $value ); 

Or maybe even, if your function is ok with null values, just simply:

do_something_with( Get_Deep_Value::get_deep_value( $data, ['one', 'two', 'three'] ) );

I’m just posting the gist here for now because I’m not quite sure how to release this as a general module in the PHP ecosystem yet. If you have any helpful suggestions, please add them in the comments!