PhpRiot
Become Zend Certified

Prepare for the ZCE exam using our quizzes (web or iPad/iPhone). More info...


When you're ready get 7.5% off your exam voucher using voucher CJQNOV23 at the Zend Store

run-phpt - execute PHPT tests

Introduction

The run-phpt command is used to execute tests in the PHPT format. If the xdebug extension is present, the command can also be used to generate code coverage. This coverage can then be used to construct a coverage report and even to intelligently detect both modified tests and tests that are affected by changes to the source code in between test runs.

The command takes as arguments a list of paths containing tests to execute, unless the --modified option is specified, then it takes as arguments the path to the tests directory and the path to the source directory. If the --modified option is not specified, and no arguments are passed, the command searches for tests in the current working directory.

--modified

The --modified or -m option, if present, implies both the --recursive and --coverage options, and is used to generate a coverage database and to use that database to detect modifications in the tests and the source. These modified tests are then executed.

The command places a file named pear2coverage.db in the tests directory, which is an Sqlite3 database containing the coverage information. The coverage can be viewed as a web-based report by taking the pear2coverage.phar.php file installed with the developer tools and placing it in a web server directory, and then browsing to it. The web server must have the phar and sqlite3 extensions enabled in order to function properly.

To illustrate how powerful this option is, imagine a hypothetical directory structure as follows:


src/
File1.php
File2.php
File3.php
tests/
test1.phpt
test2.phpt
test3.phpt
test4.phpt

Here are the source files:

File1.php:

<?php
class File1
{
    var 
$a 1;
    function 
__construct($a 1)
    {
        
$this->$a;
    }

    function 
setInternalThing($thing)
    {
        
$this->internal $thing;
        
$this->internal->initialize($this);
    }
}
?>

File2.php:

<?php
class File2
{

    function 
initialize(File1 $parent)
    {
        
$parent->2;
    }
}
?>

File3.php:

<?php
class File3 extends File2
{

    function 
initialize(File1 $parent)
    {
        
$parent->3;
    }
}
?>

test1.phpt:

--TEST--
test 1
--FILE--
<?php
function __autoload($class) { include __DIR__ '/../src/' $class '.php'; }

$test = new File1(6);
if (
$test->!= 6) {
    echo 
'$a is not 6, it is ' $test->a"\n";
}
?>
===DONE===
--EXPECT--
===DONE===

test2.phpt:

--TEST--
test 2
--FILE--
<?php
function __autoload($class) { include __DIR__ '/../src/' $class '.php'; }

$test2 = new File2;

$test = new File1;
$test->setInternalThing($test2);

if (
$test->!= 2) {
    echo 
'$a is not 2, it is ' $test->a"\n";
}
?>
===DONE===
--EXPECT--
===DONE===

test3.phpt:

--TEST--
test 3
--FILE--
<?php
function __autoload($class) { include __DIR__ '/../src/' $class '.php'; }

$test2 = new File2;

$test = new stdClass;
$test2->initialize($test);

if (
$test->!= 2) {
    echo 
'$a is not 2, it is ' $test->a"\n";
}
?>
===DONE===
--EXPECT--
===DONE===

test4.phpt:

--TEST--
test 4
--FILE--
<?php
function __autoload($class) { include __DIR__ '/../src/' $class '.php'; }

$test3 = new File3;

$test = new File1;
$test->setInternalThing($test3);

if (
$test->!= 3) {
    echo 
'$a is not 3, it is ' $test->a"\n";
}
?>
===DONE===
--EXPECT--
===DONE===

If a modification is made to File3.php, the run-phpt command will detect that only test4.phpt uses this file, and will run that test. If a modification is made to File2.php, test2.phpt, test3.phpt and test4.phpt will all be executed, even though test4.phpt does not directly use the File2 class, because File3 extends File2 and so the file is loaded. If a modification is made to File1.php, test1.phpt, test2.phpt and test4.phpt will all be executed. Finally, if any of the phpt test files are executed, or any external files that they include are modified, they will be run again. If a new test, test5.phpt is added, the run-phpt command will also detect the test and run it.

This allows extremely efficient development, as surgically running only tests that are affected by source code changes allows assurance that even the most remote file dependencies are validated, and irrelevant tests are not executed unnecessarily. By relying upon the coverage report, it is also easy to catch subtle logic bugs preventing code blocks from being executed, resulting in far more robust code much faster. Pyrus itself was developed using this technique.

--recursive

The --recursive or -r option causes Pyrus to recursively traverse directories specified

--coverage

the --coverage or -x option causes Pyrus to record coverage using the xdebug extension's code coverage capabilities.

PEAR Manual