about me about me
photography photography
software projects software projects
contact me contact me

When writing unit tests, it’s often useful to know the code coverage you’ve achieved to see what proportion of your code you’re exercising. Typically you have to commit your code to version control, so your CI server can pull in your updates and produce coverage reports. This means you sometimes commit incomplete tests, where you might forget to test failure branches (throwing exceptions for example).

code coverage report


What’s needed is a way to produce code coverage reports from PHPUnit from the command line. Just a summary would be useful. You’ll need XDebug installed for code coverage reports.

This script was inspired by Ben Downling‘s script from 2010. Unfortunately Ben’s implementation no longer works as PHPUnit has deprecated the --log-metrics switch.

Like a lemming, I chose to implement this in bash script, a language I’m not overly familiar with … if I’d used PHP to do this, it would have been cross platform!

Update: My colleague Neel stumbled across this post and generously re-wrote the core of this bash script into several PHP classes. The classes are available in one of his github projects.

I’ve done it now though, so here’s a bash script to parse PHPUnit’s XML code coverage file and provide a percentage of the statements covered:

#!/bin/bash
COVERAGE=""
METRICS="/tmp/phpunit-metrics.xml"

if [ "$1" == "--coverage" ]
then
  COVERAGE="--coverage-clover $METRICS"
  shift
fi

phpunit $COVERAGE [email protected]

# exit with PHPUnit's return code
if [ $? -ne 0 ]
then
  exit $?
fi

if [ "$COVERAGE" != "" ]
then
  echo "====================== Code Coverage Summary ====================="
  FILTER_LINES="/<class/ { print \$2 } /<metrics method/ { print \$4,\$5 }"
  JOIN_LINES="\$!N;s/\n/ /"
  TRANSFORM="s/name=\"\([A-Za-z_]*\)\" statements=\"\([0-9]*\)\" coveredstatements=\"\([0-9]*\)\"/\1\t\2\t\3/"
  RESULTS=$(cat "$METRICS" | awk "$FILTER_LINES" | sed "$JOIN_LINES" | sed "$TRANSFORM" | tr '\t' '|')
  (for line in $RESULTS; do
    CLASS=`echo "$line" | cut -d '|' -f1`;
    STATEMENTS=`echo "$line" | cut -d '|' -f2`;
    COVERED=`echo "$line" | cut -d '|' -f3`;
    COVERAGE=0
    if [[ "$STATEMENTS" > "0" && "$COVERED" > "0" ]]
    then
      COVERAGE=$(echo | awk "{print $COVERED * 100 / $STATEMENTS}")
    fi
    echo "$CLASS $COVERAGE" | awk '{printf "%-60s %.2f%\n", $1, $2}'
  done) | sort -nr --key=2
  rm "$METRICS"
fi

Assuming you’ve configured PHPUnit, and saved this to run_tests you can run your test suite with this script like so:

$ run_tests --coverage
PHPUnit 3.5.14 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 5.25Mb

OK (1 test, 1 assertion)

Writing code coverage data to XML file, this may take a moment.
====================== Code Coverage Summary ======================
MyClass                                                      89.73%

Enjoy!


comments

No comments for this post.