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.5.0 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.5.0 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.5.0 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 '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 '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()
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()
assertEmpty()
assertEqualXMLStructure()
assertEquals()
assertFalse()
assertFileEquals()
assertFileExists()
assertGreaterThan()
assertGreaterThanOrEqual()
assertInstanceOf()
assertInternalType()
assertLessThan()
assertLessThanOrEqual()
assertNull()
assertObjectHasAttribute()
assertRegExp()
assertStringMatchesFormat()
assertStringMatchesFormatFile()
assertSame()
assertSelectCount()
assertSelectEquals()
assertSelectRegExp()
assertStringEndsWith()
assertStringEqualsFile()
assertStringStartsWith()
assertTag()
assertThat()
assertTrue()
assertType()
assertXmlFileEqualsXmlFile()
assertXmlStringEqualsXmlFile()
assertXmlStringEqualsXmlString()
Copyright © 2005-2010 Sebastian Bergmann.