| Prev | Next |
One of the goals of PHPUnit (see Chapter 2) is that tests should be composable: we want to be able to run any number or combination of tests together, for instance all tests for the whole project, or the tests for all classes of a component that is part of the project, or just the tests for a single class.
PHPUnit supports different ways of organizing tests and composing them into a test suite. This chapter shows the most commonly used approaches.
Probably the easiest way to compose a test suite is to keep all test case source files in a test directory. PHPUnit can automatically discover and run the tests by recursively traversing the test directory.
Lets take a look at the test suite of the Object_Freezer library. Looking at this project's directory structure, we see that the test case classes in the Tests directory mirror the package and class structure of the System Under Test (SUT) in the Object directory:
Object Tests |-- Freezer |-- Freezer | |-- HashGenerator | |-- HashGenerator | | `-- NonRecursiveSHA1.php | | `-- NonRecursiveSHA1Test.php | |-- HashGenerator.php | | | |-- IdGenerator | |-- IdGenerator | | `-- UUID.php | | `-- UUIDTest.php | |-- IdGenerator.php | | | |-- LazyProxy.php | | | |-- Storage | |-- Storage | | `-- CouchDB.php | | `-- CouchDB | | | | |-- WithLazyLoadTest.php | | | | `-- WithoutLazyLoadTest.php | |-- Storage.php | |-- StorageTest.php | `-- Util.php | `-- UtilTest.php `-- Freezer.php `-- FreezerTest.php
To run all tests for the library we just need to point the PHPUnit command-line test runner to the test directory:
phpunit Tests
PHPUnit 3.4.14 by Sebastian Bergmann.
............................................................ 60 / 75
...............
Time: 0 seconds
OK (75 tests, 164 assertions)
To run only the tests that are declared in the Object_FreezerTest test case class in Tests/FreezerTest.php we can use the following command:
phpunit Tests/FreezerTest
PHPUnit 3.4.14 by Sebastian Bergmann.
............................
Time: 0 seconds
OK (28 tests, 60 assertions)
For more fine-grained control of which tests to run we can use the --filter switch:
phpunit --filter testFreezingAnObjectWorks Tests
PHPUnit 3.4.14 by Sebastian Bergmann.
.
Time: 0 seconds
OK (1 test, 2 assertions)
A drawback of this approach is that we have no control over the order in which the test are run. This can lead to problems with regard to test dependencies, see the section called “Test Dependencies”.
PHPUnit's XML configuration file (Appendix C) can also be used to compose a test suite. Example 7.1 shows a minimal example that will add all *Test classes that are found in *Test.php files when the Tests is recursively traversed.
Example 7.1: Composing a Test Suite Using XML Configuration
<phpunit>
<testsuites>
<testsuite name="Object_Freezer">
<directory>Tests</directory>
</testsuite>
</testsuites>
</phpunit>
A drawback of this approach is that we have no control over the order in which the test are run. This can lead to problems with regard to test dependencies, see the section called “Test Dependencies”.
Alternatively, we can make the order in which tests are executed explicit:
Example 7.2: Composing a Test Suite Using XML Configuration
<phpunit>
<testsuites>
<testsuite name="Object_Freezer">
<file>Tests/Freezer/HashGenerator/NonRecursiveSHA1Test.php</file>
<file>Tests/Freezer/IdGenerator/UUIDTest.php</file>
<file>Tests/Freezer/UtilTest.php</file>
<file>Tests/FreezerTest.php</file>
<file>Tests/Freezer/StorageTest.php</file>
<file>Tests/Freezer/Storage/CouchDB/WithLazyLoadTest.php</file>
<file>Tests/Freezer/Storage/CouchDB/WithoutLazyLoadTest.php</file>
</testsuite>
</testsuites>
</phpunit>
The PHPUnit_Framework_TestSuite class of the PHPUnit framework allows us to organize tests into a hierarchy of test suite objects.
Example 7.3 shows the top-level AllTests class for a project that has a package named Package.
Example 7.3: The top-level AllTests class
<?php
require_once 'PHPUnit/Framework.php';
require_once 'Package/AllTests.php';
// ...
class AllTests
{
public static function suite()
{
$suite = new PHPUnit_Framework_TestSuite('Project');
$suite->addTest(Package_AllTests::suite());
// ...
return $suite;
}
}
?>
The top-level AllTests class aggregates the package-level Package_AllTests class that in turn aggregates the test case classes for the classes of said package.
Example 7.4: The Package_AllTests class
<?php
require_once 'PHPUnit/Framework.php';
require_once 'Framework/ClassTest.php';
// ...
class Package_AllTests
{
public static function suite()
{
$suite = new PHPUnit_Framework_TestSuite('Package');
$suite->addTestSuite('Package_ClassTest');
// ...
return $suite;
}
}
?>
The Package_ClassTest class is a normal test case class that extends the PHPUnit_Framework_TestCase base class.
Executing phpunit AllTests in the Tests directory will run all tests.
Executing phpunit AllTests in the Tests/Package directory will run only the tests for the Package_* classes.
Executing phpunit ClassTest in the Tests/Package directory will run only the tests for the Package_Class class (which are declared in the Package_ClassTest class).
Executing phpunit --filter testSomething ClassTest in the Tests/Package directory will run only the test named testSomething from the Package_ClassTest class.
The PHPUnit_Framework_TestSuite class offers two template methods, setUp() and tearDown(), that are called before the first test of the test suite and after the last test of the test suite, respectively.
Example 7.5: The MySuite class
<?php
require_once 'MyTest.php';
class MySuite extends PHPUnit_Framework_TestSuite
{
public static function suite()
{
return new MySuite('MyTest');
}
protected function setUp()
{
print __METHOD__ . "\n";
}
protected function tearDown()
{
print __METHOD__ . "\n";
}
}
?>
The MyTest test case class that is added to the test suite MySuite in Example 7.5 has two test methods, testOne() and testTwo() as well as the setUp() and tearDown() methods. The output shows in which order these eight methods are called:
MySuite::setUp() MyTest::setUp() MyTest::testOne() MyTest::tearDown() MyTest::setUp() MyTest::testTwo() MyTest::tearDown() MySuite::tearDown()
Variables stored in $this->sharedFixture by the setUp() method of the PHPUnit_Framework_TestSuite class are available as $this->sharedFixture in all the test that are aggregated by the test suite object (see the section called “Sharing Fixture”).
A TestSuite's setUp() and tearDown() methods will be called even if no test of the test suite is run because it is, for instance, filtered.
| Prev | Next |
assertArrayHasKey()
assertClassHasAttribute()
assertClassHasStaticAttribute()
assertContains()
assertContainsOnly()
assertEqualXMLStructure()
assertEquals()
assertFalse()
assertFileEquals()
assertFileExists()
assertGreaterThan()
assertGreaterThanOrEqual()
assertLessThan()
assertLessThanOrEqual()
assertNull()
assertObjectHasAttribute()
assertRegExp()
assertSame()
assertSelectCount()
assertSelectEquals()
assertSelectRegExp()
assertStringEndsWith()
assertStringEqualsFile()
assertStringStartsWith()
assertTag()
assertThat()
assertTrue()
assertType()
assertXmlFileEqualsXmlFile()
assertXmlStringEqualsXmlFile()
assertXmlStringEqualsXmlString()
Copyright © 2005-2012 Sebastian Bergmann.