Prev Next

Chapter 4. Writing Tests for PHPUnit

Example 4.1 shows how we have to rewrite our two tests from Example 1.4 so that we can use them with PHPUnit.

Example 4.1: Testing Array and sizeof() with PHPUnit

<?php
require_once 'PHPUnit/Framework.php';

class ArrayTest extends PHPUnit_Framework_TestCase
{
public function testNewArrayIsEmpty()
{
// Create the Array fixture.
$fixture = array();

// Assert that the size of the Array fixture is 0.
$this->assertEquals(0, sizeof($fixture));
}

public function testArrayContainsAnElement()
{
// Create the Array fixture.
$fixture = array();

// Add an element to the Array fixture.
$fixture[] = 'Element';

// Assert that the size of the Array fixture is 1.
$this->assertEquals(1, sizeof($fixture));
}
}
?>

 

Whenever you are tempted to type something into a print statement or a debugger expression, write it as a test instead.

 
  --Martin Fowler

Example 4.1 shows the basic steps for writing tests with PHPUnit:

  1. The tests for a class Class go into a class ClassTest.

  2. ClassTest inherits (most of the time) from PHPUnit_Framework_TestCase.

  3. The tests are public methods that are named test*.

    Alternatively, you can use the @test annotation in a method's docblock to mark it as a test method.

  4. Inside the test methods, assertion methods such as assertEquals() (see Table 21.1) are used to assert that an actual value matches an expected value.

Data Providers

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

A data provider method must be public and static and either return an array of arrays or an object that implements the Iterator interface and yields an array for each iteration step. For each array that is part of the collection the test method will be called with the contents of the array as its arguments.

Example 4.2: Using data providers

<?php
class DataTest extends PHPUnit_Framework_TestCase
{
public static function provider()
{
return array(
array(0, 0, 0),
array(0, 1, 1),
array(1, 0, 1),
array(1, 1, 3)
);
}

/**
* @dataProvider provider
*/
public function testAdd($a, $b, $c)
{
$this->assertEquals($c, $a + $b);
}
}
?>
phpunit DataTest
PHPUnit 3.2.10 by Sebastian Bergmann.

...F

Time: 0 seconds

There was 1 failure:

1) testAdd(DataTest) with data (1, 1, 3)
Failed asserting that <integer:2> matches expected value <integer:3>.
/home/sb/DataTest.php:21

FAILURES!
Tests: 4, Failures: 1.

Testing Exceptions

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

Example 4.3: Using the @expectedException annotation

<?php
require_once 'PHPUnit/Framework.php';

class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
}
}
?>
phpunit ExceptionTest
PHPUnit 3.2.10 by Sebastian Bergmann.

F

Time: 0 seconds

There was 1 failure:

1) testException(ExceptionTest)
Expected exception InvalidArgumentException

FAILURES!
Tests: 1, Failures: 1.

Alternatively, you can use the setExpectedException() method to set the expected exception as shown in Example 4.4.

Example 4.4: Expecting an exception to be raised by the tested code

<?php
require_once 'PHPUnit/Framework.php';

class ExceptionTest extends PHPUnit_Framework_TestCase
{
public function testException()
{
$this->setExpectedException('InvalidArgumentException');
}
}
?>
phpunit ExceptionTest
PHPUnit 3.2.10 by Sebastian Bergmann.

F

Time: 0 seconds

There was 1 failure:

1) testException(ExceptionTest)
Expected exception InvalidArgumentException

FAILURES!
Tests: 1, Failures: 1.

Table 4.1 shows the methods provided for testing exceptions.

Table 4.1. Methods for testing exceptions

Method Meaning
void setExpectedException(string $exceptionName) Set the name of the expected exception to $exceptionName.
String getExpectedException() Return the name of the expected exception.

You can also use the approach shown in Example 4.5 to test exceptions.

Example 4.5: Alternative approach to testing exceptions

<?php
require_once 'PHPUnit/Framework.php';

class ExceptionTest extends PHPUnit_Framework_TestCase {
public function testException() {
try {
// ... Code that is expected to raise an exception ...
}

catch (InvalidArgumentException $expected) {
return;
}

$this->fail('An expected exception has not been raised.');
}
}
?>

If the code that is expected to raise an exception in Example 4.5 does not raise the expected exception, the subsequent call to fail() (see Table 21.3) will halt the test and signal a problem with the test. If the expected exception is raised, the catch block will be executed, and the test will end successfully.

Testing PHP Errors

By default, PHPUnit converts PHP errors, warnings, and notices that are triggered during the execution of a test to an exception. Using these exceptions, you can, for instance, expect a test to trigger a PHP error as shown in Example 4.6.

Example 4.6: Expecting a PHP error using @expectedException

<?php
class ExpectedErrorTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException PHPUnit_Framework_Error
*/
public function testFailingInclude()
{
include 'not_existing_file.php';
}
}
?>
phpunit ExpectedErrorTest
PHPUnit 3.2.21 by Sebastian Bergmann.

.

Time: 0 seconds

OK (1 test)

PHPUnit_Framework_Error_Notice and PHPUnit_Framework_Error_Warning represent PHP notices and warning, respectively.

Prev Next
1. Automating Tests
2. PHPUnit's Goals
3. Installing PHPUnit
4. Writing Tests for PHPUnit
Data Providers
Testing Exceptions
Testing PHP Errors
5. The Command-Line Test Runner
6. Fixtures
More setUp() than tearDown()
Variations
Sharing Fixture
7. Organizing Test Suites
Suite-Level Setup
8. TestCase Extensions
Testing Output
Testing Performance
9. Database Testing
Datasets
Flat XML Data Set
XML Data Set
Operations
Database Testing Best Practices
10. Incomplete and Skipped Tests
Incomplete Tests
Skipping Tests
11. Mock Objects
Self-Shunting
Stubs
12. Testing Practices
During Development
During Debugging
13. Test-First Programming
BankAccount Example
14. Code Coverage Analysis
Specifying Covered Methods
Ignoring Code Blocks
Including and Excluding Files
15. Other Uses for Tests
Agile Documentation
Cross-Team Tests
16. Logging
XML Format
Code Coverage (XML)
JavaScript Object Notation (JSON)
Test Anything Protocol (TAP)
GraphViz Markup
Test Database
17. Skeleton Generator
Annotations
18. PHPUnit and Selenium
Selenium RC
PHPUnit_Extensions_SeleniumTestCase
19. Continuous Integration
CruiseControl
phpUnderControl
Apache Maven
20. PHPUnit's Implementation
21. PHPUnit API
Overview
PHPUnit_Framework_Assert
PHPUnit_Framework_Test
PHPUnit_Framework_TestCase
PHPUnit_Framework_TestSuite
PHPUnit_Framework_TestResult
Package Structure
22. Extending PHPUnit
Subclass PHPUnit_Framework_TestCase
Assert Classes
Subclass PHPUnit_Extensions_TestDecorator
Implement PHPUnit_Framework_Test
Subclass PHPUnit_Framework_TestResult
Implement PHPUnit_Framework_TestListener
New Test Runner
A. Assertions
B. The XML Configuration File
Test Suite
Groups
Including and Excluding Files for Code Coverage
Logging
PMD Rules
Setting PHP INI settings and Global Variables
C. PHPUnit for PHP 4
D. Index
E. Bibliography
F. Copyright