Over a million developers have joined DZone.
Platinum Partner

Practical PHP Testing Patterns: Test Runner

· Web Dev Zone

The Web Dev Zone is brought to you in partnership with Mendix.  Discover how IT departments looking for ways to keep up with demand for business apps has caused a new breed of developers to surface - the Rapid Application Developer.

Tests are more PHP classes than PHP scripts, in the sense that they are not meant to be executed by themselves. Instead, they are classes which can be instantiated with the right parameters, often calculated using reflections over the class method names and annotations.

Once instantiated, the classes can be plugged in into PHPUnit and run. The Test Runner is the part of the framework which discovers, instantiates and run the various Testcases of your battery of tests.

In the case of PHPUnit, the PEAR installation places the main script at /usr/bin/phpunit: this file is a simple PHP script itself, which bootstraps PHPUnit.

Why there is a Test Runner?

The main purpose of the Test Runner is providing a place where to factor out the common logic which is handled by the test framework for you: gathering results, isolate the various tests, clean up memory and resources.

Gone are the days of require_once() statements at the top of test cases: the Test Runner of PHPUnit 3.x accepts a --bootstrap argument which should point to a script to execute once, before running the selected set of tests. The inclusion of this file is one of the facilities provided by the Test Runner, which saves you a lot of work which you would have to repeat on all your projects test suites.

A simple parallel can be made with web servers: the Test Runner provides a SPI at an higher level of abstraction, just like Apache and mod_php parse the HTTP request for you, so that your script can deal with predefined variables containing the parameters instead of a single request string.


Graphical Test runner: a graphic tool which helps you select the tests to run, and provides you the result in a window. We won't cover such tools here.

Command-Line Test Runner: the classic phpunit script, which the PEAR installation provides you with.

The power of the command line manifests itself also for Test Runner: a command-line one can easily be composed by other scripts. However, if the tools that interact with PHPUnit are PHP-based, you may want to interface directly with the PHP class that performs this work.

Phing for example provides tasks, like the <phpunit> phing element for build integration of the test suite, which have a preferred channel of communication with the Test Runner, different from the command line. In fact, the <phpunit> task creates PHPUnit objects directly, and the resulting channel is PHP-PHP instead of PHP-bash-PHP.


Here is an example of running phpunit with its Command-Line Test Runner:

[14:05:40][giorgio@Desmond:/var/www/NakedPhp]$ phpunit --colors --bootstrap tests/bootstrap.php tests/
PHPUnit 3.5.5 by Sebastian Bergmann.

............................................................ 60 / 251
...........................I...................I............ 120 / 251
................................................I........I.. 180 / 251
I.......................I................................... 240 / 251

Time: 3 seconds, Memory: 21.75Mb

OK, but incomplete or skipped tests!
Tests: 251, Assertions: 471, Incomplete: 6.

We'll make some comments on the runner script instead of showing a test example, since the Runner is part of PHPUnit and you will never have to write one.

This is probably the /usr/bin/phpunit file on your system, or the file it links to. The #! shebang is a fake comment that tells Unix systems to execute this file with the indicated program instead of as a shell script.

Since we have to execute it with PHP, we're better off opening the <?php tag to avoid accidental output, like we were in a plain old PHP script on a web server. Quality assurance tools for PHP applications are usually written in PHP, but use the command line as their interface, instead of producing HTML and responding to the HTTP request.
/* PHPUnit
* Copyright (c) 2002-2010, Sebastian Bergmann <sebastian@phpunit.de>.
* All rights reserved.
* [license cut...]
This statement includes a file from the PHP_CodeCoverage PEAR component and tells it to not include this file into code coverage reports. PHPUnit won't disturb you with coverage over its own PHP files.
require_once 'PHP/CodeCoverage/Filter.php';
PHP_CodeCoverage_Filter::getInstance()->addFileToBlacklist(__FILE__, 'PHPUNIT');

- The xdebug extension provides code coverage primitives when present.
if (extension_loaded('xdebug')) {
Fixes the include path to include the directory this file is kept in.
if (strpos('/usr/bin/php', '@php_bin') === 0) {
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path());

require_once 'PHPUnit/Autoload.php';

define('PHPUnit_MAIN_METHOD', 'PHPUnit_TextUI_Command::main');

// starts the runner
As you can see, it's all good old PHP code. In fact, PHPUnit is partially tested with phpt because, being a PHP tool, a regression in it would case its own test suite to cease working.

The Web Dev Zone is brought to you in partnership with Mendix.  Learn more about The Essentials of Digital Innovation and how it needs to be at the heart of every organization.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}