Test suite documentation

This page...

Grouping tests into suites

There are many ways to group tests together into test suites. One way is to simply place multiple test cases into a single file...

<?php
require_once(dirname(__FILE__) . '/simpletest/autorun.php');
require_once(dirname(__FILE__) . '/../classes/io.php');

class FileTester extends UnitTestCase {
    ...
}

class SocketTester extends UnitTestCase {
    ...
}
?>
As many cases as needed can appear in a single file. They should include any code they need, such as the library being tested, but need none of the SimpleTest libraries.

Occasionally special subclasses are created that methods useful for testing part of the application. These new base classes are then used in place of UnitTestCase or WebTestCase. You don't normally want to run these as test cases. Simply mark any base test cases that should not be run as abstract...

abstract class MyFileTestCase extends UnitTestCase {
    ...
}

class FileTester extends MyFileTestCase { ... }

class SocketTester extends UnitTestCase { ... }
Here the FileTester class does not contain any actual tests, but is the base class for other test cases.

We will call this sample file_test.php. Currently the test cases are grouped simply by being in the same file. We can build larger constructs just by including other test files in.

<?php
require_once('simpletest/autorun.php');
require_once('file_test.php');
?>
This will work, but create a purely flat hierarchy. INstead we create a test suite file. Our top level test suite can look like this...
<?php
require_once('simpletest/autorun.php');

class AllFileTests extends TestSuite {
    function __construct() {
        parent::__construct();
        $this->addFile('file_test.php');
    }
}
?>
What happens here is that the TestSuite class will do the require_once() for us. It then checks to see if any new test case classes have been created by the new file and automatically composes them to the test suite. This method gives us the most control as we just manually add more test files as our test suite grows.

If this is too much typing, and you are willing to group test suites together in their own directories or otherwise tag the file names, then there is a more automatic way...

<?php
require_once('simpletest/autorun.php');

class AllFileTests extends TestSuite {
    function __construct() {
        parent::__construct();
        $this->collect(dirname(__FILE__) . '/unit',
                       new SimplePatternCollector('/_test.php/'));
    }
}
?>
This will scan a directory called "unit" for any files ending with "_test.php" and load them. You don't have to use SimplePatternCollector to filter by a pattern in the filename, but this is the most common usage.

That snippet above is very common in practice. Now all you have to do is drop a file of test cases into the directory and it will run just by running the test suite script.

The catch is that you cannot control the order in which the test cases are run. If you want to see lower level components fail first in the test suite, and this will make diagnosis a lot easier, then you should manually call addFile() for these. Tests cases are only loaded once, so it's fine to have these included again by a directory scan.

Test cases loaded with the addFile method have some useful properties. You can guarantee that the constructor is run just before the first test method and the destructor is run just after the last test method. This allows you to place test case wide set up and tear down code in the constructor and destructor, just like a normal class.

Composite suites

The above method places all of the test cases into one large suite. For larger projects though this may not be flexible enough; you may want to group the tests together in all sorts of ways.

Everything we have described so far with test scripts applies to TestSuites as well...

<?php
require_once('simpletest/autorun.php');

class BigTestSuite extends TestSuite {
    function __construct() {
        parent::__construct();
        $this->addFile('file_tests.php');
    }
}
?>
This effectively adds our test cases and a single suite below the first. When a test fails, we see the breadcrumb trail of the nesting. We can even mix groups and test cases freely as long as we are careful about loops in our includes.
<?php
require_once('simpletest/autorun.php');

class BigTestSuite extends TestSuite {
    function __construct() {
        parent::__construct();
        $this->addFile('file_tests.php');
        $this->addFile('some_other_test.php');
    }
}
?>
Note that in the event of a double include, ony the first instance of the test case will be run.

References and related information...