1. Installing PHPUnit
Requirements
PHP Archive (PHAR)
Windows
Verifying PHPUnit PHAR Releases
Composer
Optional packages
2. Writing Tests for PHPUnit
Test Dependencies
Data Providers
Testing Exceptions
Testing PHP Errors
Testing Output
Error output
Edge cases
3. The Command-Line Test Runner
Command-Line Options
4. Fixtures
More setUp() than tearDown()
Variations
Sharing Fixture
Global State
5. Organizing Tests
Composing a Test Suite Using the Filesystem
Composing a Test Suite Using XML Configuration
6. Risky Tests
Useless Tests
Unintentionally Covered Code
Output During Test Execution
Test Execution Timeout
Global State Manipulation
7. Incomplete and Skipped Tests
Incomplete Tests
Skipping Tests
Skipping Tests using @requires
8. Database Testing
Supported Vendors for Database Testing
Difficulties in Database Testing
The four stages of a database test
1. Clean-Up Database
2. Set up fixture
3–5. Run Test, Verify outcome and Teardown
Configuration of a PHPUnit Database TestCase
Implementing getConnection()
Implementing getDataSet()
What about the Database Schema (DDL)?
Tip: Use your own Abstract Database TestCase
Understanding DataSets and DataTables
Available Implementations
Beware of Foreign Keys
Implementing your own DataSets/DataTables
The Connection API
Database Assertions API
Asserting the Row-Count of a Table
Asserting the State of a Table
Asserting the Result of a Query
Asserting the State of Multiple Tables
Frequently Asked Questions
Will PHPUnit (re-)create the database schema for each test?
Am I required to use PDO in my application for the Database Extension to work?
What can I do, when I get a Too much Connections Error?
How to handle NULL with Flat XML / CSV Datasets?
9. Test Doubles
Stubs
Mock Objects
Prophecy
Mocking Traits and Abstract Classes
Stubbing and Mocking Web Services
Mocking the Filesystem
10. Testing Practices
During Development
During Debugging
11. Code Coverage Analysis
Software Metrics for Code Coverage
Whitelisting Files
Ignoring Code Blocks
Specifying Covered Methods
Edge Cases
12. Other Uses for Tests
Agile Documentation
Cross-Team Tests
13. Logging
Test Results (XML)
Test Results (TAP)
Test Results (JSON)
Code Coverage (XML)
Code Coverage (TEXT)
14. Extending PHPUnit
Subclass PHPUnit_Framework_TestCase
Write custom assertions
Implement PHPUnit_Framework_TestListener
Subclass PHPUnit_Extensions_TestDecorator
Implement PHPUnit_Framework_Test
A. Assertions
assertArrayHasKey()
assertClassHasAttribute()
assertArraySubset()
assertClassHasStaticAttribute()
assertContains()
assertContainsOnly()
assertContainsOnlyInstancesOf()
assertCount()
assertEmpty()
assertEqualXMLStructure()
assertEquals()
assertFalse()
assertFileEquals()
assertFileExists()
assertGreaterThan()
assertGreaterThanOrEqual()
assertInfinite()
assertInstanceOf()
assertInternalType()
assertJsonFileEqualsJsonFile()
assertJsonStringEqualsJsonFile()
assertJsonStringEqualsJsonString()
assertLessThan()
assertLessThanOrEqual()
assertNan()
assertNull()
assertObjectHasAttribute()
assertRegExp()
assertStringMatchesFormat()
assertStringMatchesFormatFile()
assertSame()
assertStringEndsWith()
assertStringEqualsFile()
assertStringStartsWith()
assertThat()
assertTrue()
assertXmlFileEqualsXmlFile()
assertXmlStringEqualsXmlFile()
assertXmlStringEqualsXmlString()
B. Annotations
@author
@after
@afterClass
@backupGlobals
@backupStaticAttributes
@before
@beforeClass
@codeCoverageIgnore*
@covers
@coversDefaultClass
@coversNothing
@dataProvider
@depends
@expectedException
@expectedExceptionCode
@expectedExceptionMessage
@expectedExceptionMessageRegExp
@group
@large
@medium
@preserveGlobalState
@requires
@runTestsInSeparateProcesses
@runInSeparateProcess
@small
@test
@testdox
@ticket
@uses
C. The XML Configuration File
PHPUnit
Test Suites
Groups
Whitelisting Files for Code Coverage
Logging
Test Listeners
Setting PHP INI settings, Constants and Global Variables
Configuring Browsers for Selenium RC
D. Index
E. Bibliography
F. Copyright


Appendix B. Annotations

An annotation is a special form of syntactic metadata that can be added to the source code of some programming languages. While PHP has no dedicated language feature for annotating source code, the usage of tags such as @annotation arguments in documentation block has been established in the PHP community to annotate source code. In PHP documentation blocks are reflective: they can be accessed through the Reflection API's getDocComment() method on the function, class, method, and attribute level. Applications such as PHPUnit use this information at runtime to configure their behaviour.

Note

A doc comment in PHP must start with /** and end with */. Annotations in any other style of comment will be ignored.

This appendix shows all the varieties of annotations supported by PHPUnit.

@author

The @author annotation is an alias for the @group annotation (see the section called “@group”) and allows to filter tests based on their authors.

@after

The @after annotation can be used to specify methods that should be called after each test method in a test case class.

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @after
     */
    public function tearDownSomeFixtures()
    {
        // ...
    }

    /**
     * @after
     */
    public function tearDownSomeOtherFixtures()
    {
        // ...
    }
}

@afterClass

The @afterClass annotation can be used to specify static methods that should be called after all test methods in a test class have been run to clean up shared fixtures.

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @afterClass
     */
    public static function tearDownSomeSharedFixtures()
    {
        // ...
    }

    /**
     * @afterClass
     */
    public static function tearDownSomeOtherSharedFixtures()
    {
        // ...
    }
}

@backupGlobals

The backup and restore operations for global variables can be completely disabled for all tests of a test case class like this

/**
 * @backupGlobals disabled
 */
class MyTest extends PHPUnit_Framework_TestCase
{
    // ...
}

The @backupGlobals annotation can also be used on the test method level. This allows for a fine-grained configuration of the backup and restore operations:

/**
 * @backupGlobals disabled
 */
class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @backupGlobals enabled
     */
    public function testThatInteractsWithGlobalVariables()
    {
        // ...
    }
}

@backupStaticAttributes

The @backupStaticAttributes annotation can be used to back up all static property values in all declared classes before each test and restore them afterwards. It may be used at the test case class or test method level:

/**
 * @backupStaticAttributes enabled
 */
class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @backupStaticAttributes disabled
     */
    public function testThatInteractsWithStaticAttributes()
    {
        // ...
    }
}

Note

@backupStaticAttributes is limited by PHP internals and may cause unintended static values to persist and leak into subsequent tests in some circumstances.

See the section called “Global State” for details.

@before

The @before annotation can be used to specify methods that should be called before each test method in a test case class.

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @before
     */
    public function setupSomeFixtures()
    {
        // ...
    }

    /**
     * @before
     */
    public function setupSomeOtherFixtures()
    {
        // ...
    }
}

@beforeClass

The @beforeClass annotation can be used to specify static methods that should be called before any test methods in a test class are run to set up shared fixtures.

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @beforeClass
     */
    public static function setUpSomeSharedFixtures()
    {
        // ...
    }

    /**
     * @beforeClass
     */
    public static function setUpSomeOtherSharedFixtures()
    {
        // ...
    }
}

@codeCoverageIgnore*

The @codeCoverageIgnore, @codeCoverageIgnoreStart and @codeCoverageIgnoreEnd annotations can be used to exclude lines of code from the coverage analysis.

For usage see the section called “Ignoring Code Blocks”.

@covers

The @covers annotation can be used in the test code to specify which method(s) a test method wants to test:

/**
 * @covers BankAccount::getBalance
 */
public function testBalanceIsInitiallyZero()
{
    $this->assertEquals(0, $this->ba->getBalance());
}

If provided, only the code coverage information for the specified method(s) will be considered.

Table B.1 shows the syntax of the @covers annotation.

Table B.1. Annotations for specifying which methods are covered by a test

Annotation Description
@covers ClassName::methodName Specifies that the annotated test method covers the specified method.
@covers ClassName Specifies that the annotated test method covers all methods of a given class.
@covers ClassName<extended> Specifies that the annotated test method covers all methods of a given class and its parent class(es) and interface(s).
@covers ClassName::<public> Specifies that the annotated test method covers all public methods of a given class.
@covers ClassName::<protected> Specifies that the annotated test method covers all protected methods of a given class.
@covers ClassName::<private> Specifies that the annotated test method covers all private methods of a given class.
@covers ClassName::<!public> Specifies that the annotated test method covers all methods of a given class that are not public.
@covers ClassName::<!protected> Specifies that the annotated test method covers all methods of a given class that are not protected.
@covers ClassName::<!private> Specifies that the annotated test method covers all methods of a given class that are not private.
@covers ::functionName Specifies that the annotated test method covers the specified global function.

@coversDefaultClass

The @coversDefaultClass annotation can be used to specify a default namespace or class name. That way long names don't need to be repeated for every @covers annotation. See Example B.1.

Example B.1: Using @coversDefaultClass to shorten annotations

<?php
/**
 * @coversDefaultClass \Foo\CoveredClass
 */
class CoversDefaultClassTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers ::publicMethod
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
?>

@coversNothing

The @coversNothing annotation can be used in the test code to specify that no code coverage information will be recorded for the annotated test case.

This can be used for integration testing. See Example 11.3 for an example.

The annotation can be used on the class and the method level and will override any @covers tags.

@dataProvider

A test method can accept arbitrary arguments. These arguments are to be provided by a data provider method (provider() in Example 2.5). The data provider method to be used is specified using the @dataProvider annotation.

See the section called “Data Providers” for more details.

@depends

PHPUnit supports the declaration of explicit dependencies between test methods. Such dependencies do not define the order in which the test methods are to be executed but they allow the returning of an instance of the test fixture by a producer and passing it to the dependent consumers. Example 2.2 shows how to use the @depends annotation to express dependencies between test methods.

See the section called “Test Dependencies” for more details.

@expectedException

Example 2.10 shows how to use the @expectedException annotation to test whether an exception is thrown inside the tested code.

See the section called “Testing Exceptions” for more details.

@expectedExceptionCode

The @expectedExceptionCode annotation, in conjunction with the @expectedException allows making assertions on the error code of a thrown exception thus being able to narrow down a specific exception.

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException     MyException
     * @expectedExceptionCode 20
     */
    public function testExceptionHasErrorcode20()
    {
        throw new MyException('Some Message', 20);
    }
}

To ease testing and reduce duplication a shortcut can be used to specify a class constant as an @expectedExceptionCode using the "@expectedExceptionCode ClassName::CONST" syntax.

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
      * @expectedException     MyException
      * @expectedExceptionCode MyClass::ERRORCODE
      */
    public function testExceptionHasErrorcode20()
    {
      throw new MyException('Some Message', 20);
    }
}
class MyClass
{
    const ERRORCODE = 20;
}

@expectedExceptionMessage

The @expectedExceptionMessage annotation works similar to @expectedExceptionCode as it lets you make an assertion on the error message of an exception.

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException        MyException
     * @expectedExceptionMessage Some Message
     */
    public function testExceptionHasRightMessage()
    {
        throw new MyException('Some Message', 20);
    }
}

The expected message can be a substring of the exception Message. This can be useful to only assert that a certain name or parameter that was passed in shows up in the exception and not fixate the whole exception message in the test.

class MyTest extends PHPUnit_Framework_TestCase
{
     /**
      * @expectedException        MyException
      * @expectedExceptionMessage broken
      */
     public function testExceptionHasRightMessage()
     {
         $param = "broken";
         throw new MyException('Invalid parameter "'.$param.'".', 20);
     }
}

To ease testing and reduce duplication a shortcut can be used to specify a class constant as an @expectedExceptionMessage using the "@expectedExceptionMessage ClassName::CONST" syntax. A sample can be found in the section called “@expectedExceptionCode”.

@expectedExceptionMessageRegExp

The expected message can also be specified as a regular expression using the @expectedExceptionMessageRegExp annotation. This is helpful for situations where a substring is not adequate for matching a given message.

class MyTest extends PHPUnit_Framework_TestCase
{
     /**
      * @expectedException              MyException
      * @expectedExceptionMessageRegExp /Argument \d+ can not be an? \w+/
      */
     public function testExceptionHasRightMessage()
     {
         throw new MyException('Argument 2 can not be an integer');
     }
}

@group

A test can be tagged as belonging to one or more groups using the @group annotation like this

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @group specification
     */
    public function testSomething()
    {
    }

    /**
     * @group regresssion
     * @group bug2204
     */
    public function testSomethingElse()
    {
    }
}

Tests can be selected for execution based on groups using the --group and --exclude-group options of the command-line test runner or using the respective directives of the XML configuration file.

@large

The @large annotation is an alias for @group large.

If the PHP_Invoker package is installed and strict mode is enabled, a large test will fail if it takes longer than 60 seconds to execute. This timeout is configurable via the timeoutForLargeTests attribute in the XML configuration file.

@medium

The @medium annotation is an alias for @group medium. A medium test must not depend on a test marked as @large.

If the PHP_Invoker package is installed and strict mode is enabled, a medium test will fail if it takes longer than 10 seconds to execute. This timeout is configurable via the timeoutForMediumTests attribute in the XML configuration file.

@preserveGlobalState

When a test is run in a separate process, PHPUnit will attempt to preserve the global state from the parent process by serializing all globals in the parent process and unserializing them in the child process. This can cause problems if the parent process contains globals that are not serializable. To fix this, you can prevent PHPUnit from preserving global state with the @preserveGlobalState annotation.

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @runInSeparateProcess
     * @preserveGlobalState disabled
     */
    public function testInSeparateProcess()
    {
        // ...
    }
}

@requires

The @requires annotation can be used skip tests when common preconditions, like the PHP Version or installed extensions, are not met.

A complete list of possibilities and examples can be found at Table 7.3

@runTestsInSeparateProcesses

Indicates that all tests in a test class should be run in a separate PHP process.

/**
 * @runTestsInSeparateProcesses
 */
class MyTest extends PHPUnit_Framework_TestCase
{
    // ...
}

Note: By default, PHPUnit will attempt to preserve the global state from the parent process by serializing all globals in the parent process and unserializing them in the child process. This can cause problems if the parent process contains globals that are not serializable. See the section called “@preserveGlobalState” for information on how to fix this.

@runInSeparateProcess

Indicates that a test should be run in a separate PHP process.

class MyTest extends PHPUnit_Framework_TestCase
{
    /**
     * @runInSeparateProcess
     */
    public function testInSeparateProcess()
    {
        // ...
    }
}

Note: By default, PHPUnit will attempt to preserve the global state from the parent process by serializing all globals in the parent process and unserializing them in the child process. This can cause problems if the parent process contains globals that are not serializable. See the section called “@preserveGlobalState” for information on how to fix this.

@small

The @small annotation is an alias for @group small. A small test must not depend on a test marked as @medium or @large.

If the PHP_Invoker package is installed and strict mode is enabled, a small test will fail if it takes longer than 1 second to execute. This timeout is configurable via the timeoutForSmallTests attribute in the XML configuration file.

Note

Tests need to be explicitly annotated by either @small, @medium, or @large to enable run time limits.

@test

As an alternative to prefixing your test method names with test, you can use the @test annotation in a method's DocBlock to mark it as a test method.

/**
 * @test
 */
public function initialBalanceShouldBe0()
{
    $this->assertEquals(0, $this->ba->getBalance());
}

@testdox


@ticket


@uses

The @uses annotation specifies code which will be executed by a test, but is not intended to be covered by the test. A good example is a value object which is necessary for testing a unit of code.

/**
 * @covers BankAccount::deposit
 * @uses   Money
 */
public function testMoneyCanBeDepositedInAccount()
{
    // ...
}

This annotation is especially useful in strict coverage mode where unintentionally covered code will cause a test to fail. See the section called “Unintentionally Covered Code” for more information regarding strict coverage mode.