Working with PHPUnit

PHPUnit. The standard for unit testing in PHP. When rebuilding the blog tool I used a bunch of PHP Unit work in testing the bits and pieces (well, units!) and got a bit more familiar with how it worked. This week a coworker brought a really interesting object for testing, a plugin to the LimeSurvey application to provide a link to our single signon object.

Tricky things:

  1. The SSO Component works using Curl and it isn't injected
  2. The plugin itself is an extended class from a LimeSurvey base class, how the heck do I unit test that?

I thought of a few options like having a separate class, test that class, and then have the main class just call function-per-function, but that felt a bit overwrought. Looking through other options for Reflections, which still didn't work with an extends class, I found traits. So PHP class traits are properties and methods that can be shared between classes that don't need to be extended. That created the trait as a stand along function set for unit testing, that could be included into the main class as well as included in a test class that doesn't have the extends, but includes in mocks of the class functions/ properties the SSO component uses...

It worked.

  1. Take all the main functionality out of the Plugin class and put it into a trait
  2. Leaving the __construct in place as that dealt solely with parent extend functions, which aren't required in the unit test, empty out the Plugin class and include the use <trait>
  3. Create a new class in the PHPUnit tests area, also pulling in the trait via use <trait>.
  4. Build all the fun test cases against a reflection of this class to do the usual test requirements of setting private/ protected methods or properties to public so the tests can access/ verify them

Now to look at the Curl thing. I didn't want to pull in a complete Guzzle dependency as the Curl was dedicated built, other bits, etc. But the function in the library just did the curl call and pulled it back. And it is important to test the curl bit did its curl thing. So... I gave it what it wanted.

  1. Build some index.php and other files to respond in set ways to set calls, including headers
  2. Have a method in the test suite that starts the PHP server php -s localhost:8000 -t <path> against these wrapper functions
  3. The function already used properties and configuration to get urls, passwords, etc; so set that url to be localhost:8000/<whatever> and the whole curl thing actually works

Note to test headers you need to run the PHPUnit in a separate process and with xdebug on so that the php code can read headers. That's because this SSO component uses Header: Location to redirect on no-current-SSO, so that needs to be tested that it's handled correctly.

Anyone else have any other ways I could test this sort of thing? It's working really nicely, but I might have overcomplicated things.