WordPress Unit Tests naturally play a big part in making sure that new features introduced into core work as expected and that previous features do not break. And pushing forward with more test coverage is a Good Thing™.

In the last couple of plugins, I’ve released into the WordPress Plugin Repository, I’ve included unit tests with the plugin. Of course, these aren’t for the users benefit (why would they be?).

The way I see it if we’re working with open source, why not include these tests for those who may download, run, fork, test, or explore the code base?

But there’s a thing about these unit tests: They inherit from WP_UnitTestCase. And the more I work with creating plugins for fun, for profit, and for others, the more I think that unit tests we ship with our plugins don’t necessarily need to inherit from that class.

WordPress Unit Tests: The Source Code on Trac

Instead, they should inherit from the standard set of classes provided by PHPUnit.

WordPress Unit Tests and Plugins

I don’t mean to make this an either/or issue:

It’s not like I’m saying that we should be including either vanilla PHPUnit-based tests or WordPress Unit Test Cases. But I do think we need to be strategic in how we write our tests because they are a direct reflection of how we organize our code.

For instance, if we couple the business logic of our plugin or, more simply, the logic responsible for doing the actual work of our plugin, to WordPress-specific APIs all in the same class, then our coupling is too high.

This means we’re going to have to write tests that use WP_UnitTestCase.

On the other hand, if we’re able to use standard PHP unit tests with the classes that are core to our plugin, then perhaps we’re on to a stronger object-oriented architecture. After all, we can run the WordPress core unit tests at any time.

But if our plugin requires the core testing framework, are we designing our plugin in the best way possible?

I do believe there are caveats (remember, this isn’t an either/or issue). For example, if you have a class that’s working with the WordPress database or something related to the underlying schema (or perhaps even a custom table), then using the WP_UnitTestCase makes sense.

But that’s more of an exception than a rule. It’s something we should be using sparingly.

Regardless, perhaps this is a form of a litmus test when it comes to writing object-oriented WordPress plugins:

  • If the class you’re testing must use the framework for WordPress Unit Tests but it’s not testing core, is your class too tightly coupled?

And my opinion on this may change over time (as it tends to do for anyone who’s read this blog long enough). But I know that, for now, there are a couple of plugins I’d like to refactor and unit tests I need to update.


Join the conversation! 2 Comments

  1. Hey Tom,

    The class WP_UnitTestCase is built to unit-test WordPress Core. It is not meant to test plugins or themes (although it is very often abused for that).

    When testing your plugin, you need to first decide what type of tests you want to write, as you might want unit tests, functional tests, integration tests, acceptance tests, …

    If you truly intend to write unit tests (and PHPUnit hints to this being the case), using the WP_UnitTestCase immediately makes your tests completely irrelevant for unit tests. Unit tests are meant to test one single unit in isolation. Are the interaction points with other components need to be nulled, mocked, faked, or otherwise taken out of the equation. The point of a unit test is that when it fails, you can 100% rely on the error being in that one exact unit you’ve tested. As soon as you load the entire WordPress site together with your unit to be tested, this is just not given.

    Your example of needing to test WordPress database access is not an exception to that rule. For a unit test, you need to mock/fake the DB access and hard-code what values to return. If you use a real database for your tests, you’re not unit testing anymore. This does not mean that your tests are useless (they can be completely valid integration tests, for example), but they are not unit tests.

    For a good way of creating proper unit tests for WordPress plugins/themes, I recommend using https://brain-wp.github.io/BrainMonkey/ .

  2. The differentiation, Alain pointed out is not just an academic one. A very practical and important difference between unit tests (mocking everything) and integration tests (bootstraping WordPress) is speed. When developing your business logic you want to run your unit tests often and want to run them fast.

    Bootstraping WP on each process is anything than fast. I typically run these before deployment or when a part of development is completed.

Leave a Reply