Using Modern PHP with WordPress: Part 5 – Tests

Over the course of this series, we have looked at a variety of techniques I used while building the Photogramappy plugin. We’ve discussed the Dependency Injection pattern, Composer for dependency management, and I demonstrated using pure PHP libraries, abstract classes, and interfaces to build WordPress metaboxes.

While it would take weeks or months to really deep dive into everything that can be used in modern PHP development, the end goal is to demonstrate that WordPress development can be done using modern, industry-savvy PHP. I am also looking for full time work, so if you’re interested in discussing opportunities, please reach out to me.

In this final article in this series, I want to talk a little bit about testing. Testing is often difficult to build into projects, unless the expectation is set up front that this is the only way this project can be done. Testing didn’t become a “real thing” to me until I was on a project that didn’t have it. It was complicated. Very, very complicated. It seemed as we built things, other things would break. Regressions became a daily occurrence.

So we set about doing something we should have done from the start. Writing tests. Please do not follow this example and go back to write tests that you should have from the start. Incorporate tests into your daily life.

For this plugin, I’ve written 3 tests. I’ve written 2 acceptance tests and 1 integration test. It’s a fairly small plugin. And not everything is covered. 100% test coverage is a pipe dream, so don’t strive for it. In the words of Luca Tumedei, start with 1 test because 1 test is better than no tests at all.

In fact, speaking of Luca, he is the go to master when it comes to writing tests and his site is an amazing resource.

Quick definitions. Acceptance tests are something that could theoretically be driven by QA or UAT. They are a series of procedures that a user would go through and verifies the expected outcome. Integration tests look at how data flows through an application. If acceptances tests look at how a user gets from point a to point b, integration tests do the same for data. Unit tests look at only a single function or method to validate outcome. The term “unit testing” is thrown around a lot for what really should be integration testing. In fact, in most cases, I don’t use unit tests.


Codeception is what we are using as a testing framework. Some people like PHPUnit. Codeception is basically an enhanced version of that. You’ll need a JDK installed. I used Oracle’s OpenJDK. After that, you’ll need to install Selenium Standalone Server. This runs on Java (thus needing JDK) and is a popular standalone testing server. Note: I’m linking to an older version because of incompatibilities with PHP. These incompatibilities may be fixed in the future, but for now, I’m linking to version 3.4.0. Finally, you’ll need ChromeDriver.

With these three things installed, from your terminal, execute this command to run the acceptance testing suite.

vendor/codeception/codeception/codecept run acceptance

// Output:
➜  photogramappy git:(master) ✗ vendor/codeception/codeception/codecept run acceptance
Codeception PHP Testing Framework v2.5.2
Powered by PHPUnit 6.5.13 by Sebastian Bergmann and contributors.
Running with seed:

Acceptance Tests (2) -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
✔ Geo_CoordinateCest: Verify that the Latitude Field can be saved (8.55s)
✔ Geo_CoordinateCest: Verify that the Latitude Field can be saved (8.28s)

Time: 23.37 seconds, Memory: 30.00MB

OK (2 tests, 2 assertions)

Pretty simple, right? 2 tests, 2 passes. But what about integration tests? Practically, I’ll usually write more of these but as a point of example (and because 1 test is better than no tests, amirite?):

vendor/codeception/codeception/codecept run integration

// Output
➜  photogramappy git:(master) ✗ vendor/codeception/codeception/codecept run integration
Codeception PHP Testing Framework v2.5.2
Powered by PHPUnit 6.5.13 by Sebastian Bergmann and contributors.
Running with seed:

Integration Tests (1) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
✔ TechnosailorPhotogramappyGoogle_MapsMapTest: Test_google_maps_url_is_constructed_correctly (0.05s)

Time: 2.38 seconds, Memory: 30.25MB

OK (1 test, 4 assertions)

All this test does is verify that the Google Maps URL is formed correctly in this class. Note: This series doesn’t actually touch on the Google Maps integration because it’s a pretty basic user experience. It takes the latitude and longitude from our metaboxes, and constructs a URL for the Google Maps Static API. It’s pretty low-tech.

One other sidenote here that is important to note. The Google Maps class uses a second class I briefly touched on earlier in the series. It uses the Default class (that is injected into the Maps class via DI (yay!). You might look at that class and wonder why I don’t use a simple array to setup default values. Simply, because arrays are ad hoc, do not have a predefined structure, are harder for IDEs to autocomplete, or typehint against. Arrays have their purpose, but in many cases, an array, while simpler, isn’t up to the job like a class is. The more you know! (Oh and look at this! And this! And this!

So as I bring this series to an end, I hope it’s been useful for other developers, particularly WordPress developers. One of the parts of my job over the years that I’ve enjoyed the most is mentoring. People used to comment about how verbose I can be in communicating. Sometimes I over-communicate, but that is a trait that comes from wanting people to understand why things should be done in a particular fashion (although I’m not always right).

I also want to showcase my work, and why I do it the way I do it. So if you’re looking for an experienced PHP and WordPress developer with over 14 years in the industry, who has a penchant for teamwork, forward-thinking development practices, and who has 2 adorable dogs… hire me.

  • Category: PHP