For most uses, PHPUnit has a simple API: subclass
PHPUnit2_Framework_TestCase
for your test cases and
call assertTrue()
or assertEquals()
.
However, for those of you who would like to look deeper into PHPUnit,
here are all of its published methods and classes.
Most of the time, you will encounter five classes or interfaces when you are using PHPUnit:
PHPUnit2_Framework_Assert
A collection of static methods for checking actual values against expected values.
PHPUnit2_Framework_Test
The interface of all objects that act like tests.
PHPUnit2_Framework_TestCase
A single test.
PHPUnit2_Framework_TestSuite
A collection of tests.
PHPUnit2_Framework_TestResult
A summary of the results of running one or more tests.
Figure 14.1
shows the relationship of the five basic classes and interfaces
in PHPUnit: PHPUnit2_Framework_Assert
,
PHPUnit2_Framework_Test
,
PHPUnit2_Framework_TestCase
,
PHPUnit2_Framework_TestSuite
, and
PHPUnit2_Framework_TestResult
.
Most test cases written for PHPUnit are derived indirectly from the class
PHPUnit2_Framework_Assert
, which contains methods for
automatically checking values and reporting discrepancies. The methods
are declared static, so you can write design-by-contract style
assertions in your methods and have them reported through PHPUnit
(Example 14.1).
Example 14.1: Design-by-Contract Style Assertions
<?php
require_once 'PHPUnit2/Framework/Assert.php';
class Sample {
public function aSampleMethod($object) {
PHPUnit2_Framework_Assert::assertNotNull($object);
}
}
$sample = new Sample;
$sample->aSampleMethod(NULL);
?>
Fatal error: Uncaught exception 'PHPUnit2_Framework_AssertionFailedError' with message 'expected: <NOT NULL> but was: <NULL>'
Most of the time, though, you'll be checking the assertions inside of tests.
There are two variants of each of the assertion methods: one takes a message to be displayed with the error as a parameter, and one does not. The optional message is typically displayed when a failure is displayed, which can make debugging easier.
Example 14.2: Using assertions with messages
<?php
require_once 'PHPUnit2/Framework/TestCase.php';
class MessageTest extends PHPUnit2_Framework_TestCase {
public function testMessage() {
$this->assertTrue(FALSE, 'This is a custom message.');
}
}
?>
The following example shows the output you get when you run the
testMessage()
test from
Example 14.2, using
assertions with messages:
phpunit MessageTest.php
PHPUnit 2.3.0 by Sebastian Bergmann.
F
Time: 0.102507
There was 1 failure:
1) testMessage(MessageTest)
This is a custom message.
FAILURES!!!
Tests run: 1, Failures: 1, Errors: 0, Incomplete Tests: 0.
Table 14.1 shows all the varieties of assertions.
Table 14.1. Assertions
Assertion | Meaning |
---|---|
void assertTrue(Boolean $condition) | Reports an error if $condition is FALSE . |
void assertTrue(Boolean $condition, String $message) | Reports an error identified by $message if $condition is FALSE . |
void assertFalse(Boolean $condition) | Reports an error if $condition is TRUE . |
void assertFalse(Boolean $condition, String $message) | Reports an error identified by $message if $condition is TRUE . |
void assertNull(Mixed $variable) | Reports an error if $variable is not NULL . |
void assertNull(Mixed $variable, String $message) | Reports an error identified by $message if $variable is not NULL . |
void assertNotNull(Mixed $variable) | Reports an error if $variable is NULL . |
void assertNotNull(Mixed $variable, String $message) | Reports an error identified by $message if $variable is NULL . |
void assertSame(Object $expected, Object $actual) | Reports an error if the two variables $expected and $actual do not reference the same object. |
void assertSame(Object $expected, Object $actual, String $message) | Reports an error identified by $message if the two variables $expected and $actual do not reference the same object. |
void assertSame(Mixed $expected, Mixed $actual) | Reports an error if the two variables $expected and $actual do not have the same type and value. |
void assertSame(Mixed $expected, Mixed $actual, String $message) | Reports an error identified by $message if the two variables $expected and $actual do not have the same type and value. |
void assertNotSame(Object $expected, Object $actual) | Reports an error if the two variables $expected and $actual reference the same object. |
void assertNotSame(Object $expected, Object $actual, String $message) | Reports an error identified by $message if the two variables $expected and $actual reference the same object. |
void assertNotSame(Mixed $expected, Mixed $actual) | Reports an error if the two variables $expected and $actual have the same type and value. |
void assertNotSame(Mixed $expected, Mixed $actual, String $message) | Reports an error identified by $message if the two variables $expected and $actual have the same type and value. |
void assertEquals(Array $expected, Array $actual) | Reports an error if the two arrays $expected and $actual are not equal. |
void assertEquals(Array $expected, Array $actual, String $message) | Reports an error identified by $message if the two arrays $expected and $actual are not equal. |
void assertNotEquals(Array $expected, Array $actual) | Reports an error if the two arrays $expected and $actual are equal. |
void assertNotEquals(Array $expected, Array $actual, String $message) | Reports an error identified by $message if the two arrays $expected and $actual are equal. |
void assertEquals(Float $expected, Float $actual, Float $delta = 0) | Reports an error if the two floats $expected and $actual are not within $delta of each other. |
void assertEquals(Float $expected, Float $actual, String $message, Float $delta = 0) | Reports an error identified by $message if the two floats $expected and $actual are not within $delta of each other. |
void assertNotEquals(Float $expected, Float $actual, Float $delta = 0) | Reports an error if the two floats $expected and $actual are within $delta of each other. |
void assertNotEquals(Float $expected, Float $actual, String $message, Float $delta = 0) | Reports an error identified by $message if the two floats $expected and $actual are within $delta of each other. |
void assertEquals(String $expected, String $actual) | Reports an error if the two strings $expected and $actual are not equal. The error is reported as the delta between the two strings. |
void assertEquals(String $expected, String $actual, String $message) | Reports an error identified by $message if the two strings $expected and $actual are not equal. The error is reported as the delta between the two strings. |
void assertNotEquals(String $expected, String $actual) | Reports an error if the two strings $expected and $actual are equal. |
void assertNotEquals(String $expected, String $actual, String $message) | Reports an error identified by $message if the two strings $expected and $actual are equal. |
void assertEquals(Mixed $expected, Mixed $actual) | Reports an error if the two variables $expected and $actual are not equal. |
void assertEquals(Mixed $expected, Mixed $actual, String $message) | Reports an error identified by $message if the two variables $expected and $actual are not equal. |
void assertNotEquals(Mixed $expected, Mixed $actual) | Reports an error if the two variables $expected and $actual are equal. |
void assertNotEquals(Mixed $expected, Mixed $actual, String $message) | Reports an error identified by $message if the two variables $expected and $actual are equal. |
void assertContains(Mixed $needle, Array $haystack) | Reports an error if $needle is not an element of $haystack . |
void assertContains(Mixed $needle, Array $haystack, String $message) | Reports an error identified by $message if $needle is not an element of $haystack . |
void assertNotContains(Mixed $needle, Array $haystack) | Reports an error if $needle is an element of $haystack . |
void assertNotContains(Mixed $needle, Array $haystack, String $message) | Reports an error identified by $message if $needle is an element of $haystack . |
void assertContains(Mixed $needle, Iterator $haystack) | Reports an error if $needle is not an element of $haystack . |
void assertContains(Mixed $needle, Iterator $haystack, String $message) | Reports an error identified by $message if $needle is not an element of $haystack . |
void assertNotContains(Mixed $needle, Iterator $haystack) | Reports an error if $needle is an element of $haystack . |
void assertNotContains(Mixed $needle, Iterator $haystack, String $message) | Reports an error identified by $message if $needle is an element of $haystack . |
void assertRegExp(String $pattern, String $string) | Reports an error if $string does not match the regular expression $pattern . |
void assertRegExp(String $pattern, String $string, String $message) | Reports an error identified by $message if $string does not match the regular expression $pattern . |
void assertNotRegExp(String $pattern, String $string) | Reports an error if $string matches the regular expression $pattern . |
void assertNotRegExp(String $pattern, String $string, String $message) | Reports an error identified by $message if $string matches the regular expression $pattern . |
void assertType(String $expected, Mixed $actual) | Reports an error if the variable $actual is not of type $expected . |
void assertType(String $expected, Mixed $actual, String $message) | Reports an error identified by $message if the variable $actual is not of type $expected . |
void assertNotType(String $expected, Mixed $actual) | Reports an error if the variable $actual is of type $expected . |
void assertNotType(String $expected, Mixed $actual, String $message) | Reports an error identified by $message if the variable $actual is of type $expected . |
You may find that you need other assertions than these to compare
objects specific to your project. Create your own Assert
class to contain these assertions to simplify your tests.
Failing assertions all call a single bottleneck method,
fail(String $message)
, which throws an
PHPUnit2_Framework_AssertionFailedError
. There is
also a variant which takes no parameters. Call fail()
explicitly when your test encounters an error. The test for an expected
exception is an example.
Table 14.2 lists the
bottlenext methods in PHPUnit.
PHPUnit2_Framework_Test
is the generic interface
used by all objects that can act as tests. Implementors may represent
one or more tests. The two methods are shown in
Table 14.3.
Table 14.3. Implementor Methods
Method | Meaning |
---|---|
int countTestCases() | Return the number of tests. |
void run(PHPUnit2_Framework_TestResult $result) | Run the tests and report the results on $result . |
PHPUnit2_Framework_TestCase
and
PHPUnit2_Framework_TestSuite
are the two most
prominent implementors of PHPUnit2_Framework_Test
.
You can implement PHPUnit2_Framework_Test
yourself.
The interface is kept small intentionally so it will be easy to
implement.
Your test-case classes will inherit from
PHPUnit2_Framework_TestCase
. Most of the time, you
will run tests from automatically created test suites. In this case,
each of your tests should be represented by a method named
test*
(by convention).
PHPUnit2_Framework_TestCase
implements
PHPUnit2_Framework_Test::countTestCases()
so that it
always returns 1
. The implementation of
PHPUnit2_Framework_Test::run(PHPUnit2_Framework_TestResult $result)
in this class runs setUp()
, runs the test method,
and then runs tearDown()
, reporting any exceptions
to the PHPUnit2_Framework_TestResult
.
Table 14.4 shows the
external protocol implemented by PHPUnit2_Framework_TestCase
.
Table 14.4. TestCase external protocols
Method | Meaning |
---|---|
__construct() | Creates a test case. |
__construct(String $name) | Creates a named test case. Names are used to print the test case and often as the name of the test method to be run by reflection. |
String getName() | Return the name of the test case. |
void setName($name) | Set the name of the test case. |
PHPUnit2_Framework_TestResult run(PHPUnit2_Framework_TestResult $result) | Convenience method to run the test case and report it in $result . |
void runTest() | Override with a testing method if you do not want the testing method to be invoked by reflection. |
There are two template methods -- setUp()
and
tearDown()
-- you can override to create and
dispose of the objects against which you are going to test.
Table 14.5 shows
these methods.
Table 14.5. Template Methods
Method | Meaning |
---|---|
void setUp() | Override to create objects against which to test. Each test that runs will be run in its own test case, and setUp() will be called separately for each one. |
void tearDown() | Override to dispose of objects no longer needed once the test has finished. In general, you only need to explicitly dispose of external resources (files or sockets, for example) in tearDown() . |
A PHPUnit2_Framework_TestSuite
is a composite of
PHPUnit2_Framework_Test
s. At its simplest, it
contains a bunch of test cases, all of which are run when the suite is
run. Since it is a composite, however, a suite can contain suites which
can contain suites and so on, making it easy to combine tests from
various sources and run them together.
In addition to the PHPUnit2_Framework_Test
protocol --
run(PHPUnit2_Framework_TestResult $result)
and
countTestCases()
-- PHPUnit2_Framework_TestSuite
contains protocol to create named or unnamed instances.
Table 14.6 shows the
instance creation protocol for PHPUnit2_Framework_TestSuite
.
Table 14.6. Creating named or unnamed instances
Method | Meaning |
---|---|
__construct() | Return an empty test suite. |
__construct(String $theClass) | Return a test suite containing an instance of the class named $theClass for each method in the class named test* . If no class of name $theClass exists an empty test suite named $theClass is returned. |
__construct(String $theClass, String $name) | Return a test suite named $name containing an instance of the class named $theClass for each method in the class named test* . |
__construct(ReflectionClass $theClass) | Return a test suite containing an instance of the class represented by $theClass for each method in the class named test* . |
__construct(ReflectionClass $theClass, $name) | Return a test suite named $name containing an instance of the class represented by $theClass for each method in the class named test* . |
String getName() | Return the name of the test suite. |
void setName(String $name) | Set the name of the test suite. |
PHPUnit2_Framework_TestSuite
also contains protocol
for adding and retrieving PHPUnit2_Framework_Test
s,
as shown in Table 14.7.
Table 14.7. Protocol for adding and retrieving tests
Method | Meaning |
---|---|
void addTest(PHPUnit2_Framework_Test $test) | Add $test to the suite. |
void addTestFile(String $filename) | Add the tests that are defined in the class(es) of a given sourcefile to the suite. |
void addTestFiles(Array $filenames) | Add the tests that are defined in the classes of the given sourcefiles to the suite. |
int testCount() | Return the number of tests directly (not recursively) in this suite. |
PHPUnit2_Framework_Test[] tests() | Return the tests directly in this suite. |
PHPUnit2_Framework_Test testAt(int $index) | Return the test at the $index . |
Example 14.3 shows how to create and run a test suite.
Example 14.3: Creating and running a test suite
<?php
require_once 'PHPUnit2/Framework/TestSuite.php';
require_once 'ArrayTest.php';
// Create a test suite that contains the tests
// from the ArrayTest class.
$suite = new PHPUnit2_Framework_TestSuite('ArrayTest');
// Run the tests.
$suite->run();
?>
For an example on how to use PHPUnit2_Framework_TestSuite
to hierarchically compose test cases let us look at PHPUnit's own test
suite.
Example 14.4 shows a cut-down
version of Tests/AllTests.php
,
Example 14.5 a
cut-down version of Tests/Framework/AllTests.php
.
Example 14.4: The AllTests class
<?php
if (!defined('PHPUnit2_MAIN_METHOD')) {
define('PHPUnit2_MAIN_METHOD', 'AllTests::main');
}
require_once 'PHPUnit2/Framework/TestSuite.php';
require_once 'PHPUnit2/TextUI/TestRunner.php';
require_once 'Framework/AllTests.php';
// ...
class AllTests {
public static function main() {
PHPUnit2_TextUI_TestRunner::run(self::suite());
}
public static function suite() {
$suite = new PHPUnit2_Framework_TestSuite('PHPUnit');
$suite->addTest(Framework_AllTests::suite());
// ...
return $suite;
}
}
if (PHPUnit2_MAIN_METHOD == 'AllTests::main') {
AllTests::main();
}
?>
Example 14.5: The Framework_AllTests class
<?php
if (!defined('PHPUnit2_MAIN_METHOD')) {
define('PHPUnit2_MAIN_METHOD', 'Framework_AllTests::main');
}
require_once 'PHPUnit2/Framework/TestSuite.php';
require_once 'PHPUnit2/TextUI/TestRunner.php';
require_once 'Framework/AssertTest.php';
// ...
class Framework_AllTests {
public static function main() {
PHPUnit2_TextUI_TestRunner::run(self::suite());
}
public static function suite() {
$suite = new PHPUnit2_Framework_TestSuite('PHPUnit Framework');
$suite->addTestSuite('Framework_AssertTest');
// ...
return $suite;
}
}
if (PHPUnit2_MAIN_METHOD == 'Framework_AllTests::main') {
Framework_AllTests::main();
}
?>
The Framework_AssertTest
class is a standard test case
that extends PHPUnit2_Framework_TestCase
.
Running Tests/AllTests.php
uses the TextUI
test runner to run all tests while running
Tests/Framework/AllTests.php
runs only the tests
for the PHPUnit2_Framework_*
classes.
This example shows the PHPUnit test suite running:
php AllTests.php
PHPUnit 2.3.0 by Sebastian Bergmann.
.........................................
.........................................
.......
Time: 4.642600
OK (89 tests)
While you are running all these tests, you need somewhere to store all
the results: how many tests ran, which failed, and how long they took.
PHPUnit2_Framework_TestResult
collects these results.
A single PHPUnit2_Framework_TestResult
is passed
around the whole tree of tests; when a test runs or fails, the fact is
noted in the PHPUnit2_Framework_TestResult
. At the
end of the run, PHPUnit2_Framework_TestResult
contains a summary of all the tests.
PHPUnit2_Framework_TestResult
is also a subject than
can be observed by other objects wanting to report test progress. For
example, a graphical test runner might observe the
PHPUnit2_Framework_TestResult
and update a progress
bar every time a test starts.
Table 14.8 summarizes
the external protocols of PHPUnit2_Framework_TestResult
.
Table 14.8. TestResult external protocols
Method | Meaning |
---|---|
void addError(PHPUnit2_Framework_Test $test, Exception $e) | Record that running $test caused $e to be thrown unexpectedly. |
void addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) | Record that running $test caused $e to be thrown unexpectedly. |
PHPUnit2_Framework_TestFailure[] errors() | Return the errors recorded. |
PHPUnit2_Framework_TestFailure[] failures() | Return the failures recorded. |
PHPUnit2_Framework_TestFailure[] notImplemented() | Return the incomplete test cases recorded. |
int errorCount() | Return the number of errors. |
int failureCount() | Return the number of failures. |
int notImplementedCount() | Return the number of incomplete test cases. |
int runCount() | Return the total number of test cases run. |
Boolean wasSuccessfull() | Return whether or not all tests ran successfully. |
Boolean allCompletlyImplemented() | Return whether or not all tests were completely implemented. |
void collectCodeCoverageInformation(Boolean $flag) | Enables or disables the collection of Code Coverage information. |
Array getCodeCoverageInformation() | Return the code coverage information collected. |
If you want to register as an observer of a
PHPUnit2_Framework_TestResult
, you need to implement
PHPUnit2_Framework_TestListener
. To register, call
addListener()
, as shown in
Table 14.9.
Table 14.9. TestResult and TestListener
Method | Meaning |
---|---|
void addListener(PHPUnit2_Framework_TestListener $listener) | Register $listener to receive updates as results are recorded in the test result. |
void removeListener(PHPUnit2_Framework_TestListener $listener) | Unregister $listener from receiving updates. |
Table 14.10 shows the methods that test listeners implement; also see Example 15.3.
Table 14.10. TestListener Callbacks
Method | Meaning |
---|---|
void addError(PHPUnit2_Framework_Test $test, Exception $e) | $test has thrown $e . |
void addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) | $test has failed an assertion, throwing a kind of PHPUnit2_Framework_AssertionFailedError . |
void addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) | $test is an incomplete test. |
void startTestSuite(PHPUnit2_Framework_TestSuite $suite) | $suite is about to be run. |
void endTestSuite(PHPUnit2_Framework_TestSuite $suite) | $suite has finished running. |
void startTest(PHPUnit2_Framework_Test $test) | $test is about to be run. |
void endTest(PHPUnit2_Framework_Test $test) | $test has finished running. |
Many of the classes mentioned so far in this book come from
PHPUnit2/Framework
. Here are all the packages in
PHPUnit:
PHPUnit2/Framework
The basic classes in PHPUnit.
PHPUnit2/Extensions
Extensions to the PHPUnit framework.
PHPUnit2/Runner
Abstract support for running tests.
PHPUnit2/TextUI
The text-based test runner.
PHPUnit2/Util
Utility classes used by the other packages.