Archive for June, 2016

Ask me about Unit Testing and I’ll probably say, “nice to have”. Unit tests are very nice to have … but sometimes the project schedule doesn’t include time to build the unit tests — which often take nearly as much time as writing the functional code. But when I have time, I really like good unit tests.

I’ve never found a PHP unit test framework that I like, so I roll my own. It’s evolved over time from “call functions and see if they fail” to “test all scenarios and track complete coverage”. Here’s the basic framework I use:

  1. All PHP files can conduct their own unit tests by simply executing them from the command line, e.g.
    • ]# php Project.php
  2. A script will run all unit tests
    • ]# ./
  3. All PHP functions declare their usage so that coverage can be tracked

A “hello world” class of mine looks something like this:

class HelloWorld {
  function findWorld() {
    return "Earth";
  function findGalaxy() {
    return "Milky Way";
// Unit Tests
function doUnitTests_HelloWorld() {
  // Only run tests when executed from the command line
  if (!(php_sapi_name() == "cli")) return;
  // Only run tests when it's THIS file that's executed from the command line
  global $argv;
  if (pathinfo(__FILE__, PATHINFO_FILENAME) != pathinfo($argv[0],PATHINFO_FILENAME)) return;
  // Create coverage arrays
  global $__localAllCoverage, $__localCoverage;
  $__localAllCoverage = [
  $__localCoverage = [];

  echo "HelloWorld.php unit tests\n";

  $msg = "findWorld test";
  $hw = new HelloWorld();
  if ($hw->findWorld() != 'Earth') {
  } else {
    echo "Success $msg\n";

  $msg = "findGalaxy test";
  if ($hw->findGalaxy() != 'Milky Way') {
  } else {
    echo "Success $msg\n";

  $diff = array_diff($__localAllCoverage,$__localCoverage);
  if (count($diff) != 0) {
    unitTestFailed('Tests did not have complete coverate.',[$__localAllCoverage,$__localCoverage,$diff]);

  echo "\n\033[32m Success! \033[0m \n";

And the unit test functions in unitTests.php look like this:

function unitTestCoverage($__f) {
  if (!(php_sapi_name() == "cli")) return;

  // Running unit tests!
  global $__localCoverage;

  if (!in_array($__f,$__localCoverage)) {
    echo " .. {\033[94m" . end($__localCoverage) . "\033[0m} .. ";
function unitTestFailed($msg,$data) {
  foreach ($data as $d) {
  echo "\n \033[31m FAILED $msg \033[0m \n";

In my script that runs every unit test, I check for the failure exit codes:


cd www/api/classes


for i in "${files[@]}"
  php $i
  if [ $? -ne 0 ]
    echo -e "\n\nFAILURE in ${i}\n"
    exit 1

echo -e "\n\nALL TESTS PASSED!\n"

exit 0

I hope you like this framework as much as I do! It has ensured full unit test coverage and cut way down on bugs that get to a test or production stage.