Last week I had the pleasure of attending WordCamp Cape Town 2018 and hosting a workshop on PHPUnit and Test Driven Development. I find reviewing slides from talks to be too abstract to be of much help (unless you’re reviewing slides in a panic a week before you are due to present and need to reassure yourself that you don’t have to deliver the equivalent of a Steve Jobs keynote). So, for the benefit of anyone who wasn’t there and is interested (and the Head Organiser told me he was, so there), here is a multi-part summary of what I rambled on about on that fateful Thursday afternoon in Salt River starting with getting set-up with the workshop files and what some of the basic setup is all about.
If you want to get involved, then you will need the following:
- GIT repo for the example files I wrote for the workshop
- Local install of WordPress
- WordPress test repo
Follow the details in the GIT repo readme file for how best to go about achieving the above. The GIT repo has already been configured for testing. To do this I ssh’ed into my vagrant install and did the following:
$ cd /srv/www/wordpress-default/public_html/wp-content/plugins/wordcamp-tdd/ $ wp scaffold plugin wordcamp-tdd Success: Created plugin files. Success: Created test files.
nb: I put the plugin from the GIT repo into the default wordpress install that comes pre-baked into VVV.
Among other things, this creates a bootstrap file, which, all being well, bootstraps PHPUnit with everything you need to test your plugin with WP Unit.
The other file to have a look at is an XML config file called phpunit.xml.dist. I made some modifications to this to highlight some things you can do to make life easier when your test suites get large, and also because I got upset when Codesniffer starts shouting at me.
First up, if you use codesniffer and the WordPress codesniffs, then you will get called out for using filenames for your test files like test-sometest.php as filenames for classes must be prefixed with “class”. Much though I love to see myself as a rebel who bows to no man, I meekly change my test structure to have a prefix of “class-” and suffix of “-tests.php”. The prefix because I blindly follow all WordPress directives and the suffix because you may want to include some helper classes for your tests and not want them executed as tests.
Also thrown in for good measure, I’ve shown how I define a testsuite, in this case my completed tests. These could be run with:
$ phpunit --testsuite completed
Also, I haven’t included a group called external_api_http_tests, but should you end up with a test suite that includes lengthy tests that act on external APIs, or that are just time consuming to run, you may wish to exclude them from your default tests and only run them specifically when you are about to deploy. In this example, running
would not run any tests with @group external_api_http_tests in its docblock (and all your tests will have docblocks or WordPress codesniffer will unleash a botnet the likes of which you’ve never seen before. Possibly), while
$ phpunit --group external_api_http_tests
would run those tests.
If this is a level above where you are at with testing right now, or simply irrelevant, then do what my wife does when I start waffling on about things that are of no consequence right now (Spurs performances in the premier league, a new code trick I’ve learned, one of my kids has set the dog on fire again) and ignore me.
Last thing from a set-up point of view, a quick look at an example test:
A few points to note:
Namespace: I often namespace the test with the same namespace as the class I am testing. In this instance I’m not testing any specific class so went with the namespace the test sits in. I have yet to hear any arguments for or against this so am happy with this as a set-up until someone cleverer than me raps my knuckles and tells me I’m a moron for doing this.
Class name: You can call your class any name you want. I tend to match the filename of the test, but it will run anyway even if you don’t (you anarchist) just ensure that you extend WP_UnitTestCase to make use of WP_Unit. The forward slash in front of WP_UnitTestCase is to break out of the namespace the tests are in. If you aren’t namespacing, omit this.
Method names: You can indicate tests by adding @test to the docblock, but I prefer to do so by prefixing all my test methods with “test_” because I learned this first and I need to do things a ton of times before my stubborn brain begrudgingly makes an attempt to remember it and I forget to add @test. That said either works fine. The this_wont_run method shown, yes you guessed it, wont run because it is not prefixed with “test_”.
So, we’re set-up, we know what we’re up too, and we’re ready to start testing, or are we?
Given that its taken an hour of me typing and screen-shotting away to get us this far, is this really worth the effort? Isn’t testing yet another stick that old farts of the development world bash people with to stop them learning fun things like Python, machine learning and algorithms that will convince us to name our children Mark Zuckerberg?
Tune in this time next week for the continuation of the write-up of my WordCamp workshop including my compelling arguments for why you should test along with a practical real world example that is literally rocket science*