PHP DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


Testing PHP Code with PHPUnit

by Sebastian Bergmann, author of PHPUnit Pocket Guide
12/08/2005

The release of PHP 5 in July 2004 marked a significant leap in PHP's evolution--it enabled the development of large-scale applications to leverage the productivity, maintainability, and reusability of object-oriented design. While the language features introduced in PHP 5 are vital for this, the development of large-scale applications requires additional tools and techniques to be viable.

PHPUnit is such a tool. It supports the development of object-oriented PHP applications using the concepts and methods of Agile Programming, Extreme Programming, Test-Driven Development, and Design-by-Contract Development by providing an elegant and robust framework for the creation, execution, and analysis of unit tests.

Automating Tests

Even good programmers make mistakes. The difference between a good programmer and a bad programmer is that the good programmer uses tests to detect his mistakes as soon as possible. The sooner you test for a mistake, the greater your chance of finding it and the less it will cost to find and fix. This explains why leaving testing until just before releasing the software is so problematic. Most errors are not caught at all, and the cost of fixing the ones you do catch is so high that you have to perform triage with the errors because you just cannot afford to fix them all.

Testing with PHPUnit is an activity not totally different from what you should already be doing. It is just a different way of doing it. The difference is between testing (that is, checking that your program behaves as expected) and performing a battery of tests (using runnable code fragments that automatically test the correctness of parts, or units, of the software). These runnable code fragments are called unit tests.

Imagine that your current task is to test PHP's built-in Array. One feature to test is the function sizeof(). For a newly created array, you expect the sizeof() function to return 0. After an element is added, sizeof() should return 1. When you start to test the numerous array_*() functions PHP offers, you need to write a test for each of them. You could write the infrastructure for all these tests from scratch. However, it is much better to write a testing infrastructure once and then write only the unique parts of each test.

Testing with PHPUnit

PHPUnit is such an infrastructure. It is a family of PEAR packages (PHPUnit, PHPUnit2) that I designed after proven solutions from the Java world (JUnit, junitour, and TestDox) and that is available from the PHP Extension and Application Repository (PEAR), a framework and distribution system for reusable PHP components. You can install it using the PEAR Installer by running

pear install PHPUnit2

Due to PEAR's version naming standard, the PHPUnit package for PHP 5 is PHPUnit2.

The following example shows how you have to write your two tests to use them with PHPUnit.

Example 1. Testing Array and sizeof() with PHPUnit

<?php
require_once 'PHPUnit2/Framework/TestCase.php';

class ArrayTest extends PHPUnit2_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));
    }
}
?>

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

  • The tests for a class Class go into a class ClassTest.
  • ClassTest inherits (most of the time) from PHPUnit2_Framework_TestCase.
  • The tests are public methods that expect no parameters and are named test*.
  • Inside the test, assertion methods such as assertEquals() assert that an actual value matches an expected value.

Invoke the PHPUnit command-line test runner through the phpunit command. The following code shows how to run tests with the PHPUnit command-line test runner:

$ phpunit ArrayTest
PHPUnit 2.3.0 by Sebastian Bergmann.

..

Time: 0.067288

OK (2 tests)

For each test run, the PHPUnit command-line tool prints one character to indicate progress:

.
Printed when the test succeeds.
F
Printed when an assertion fails while running the test method.
E
Printed when an error occurs while running the test method.
I
Printed when the test is marked as being incomplete or not yet implemented.

PHPUnit distinguishes between failures and errors. A failure is a violated PHPUnit assertion. An error is an unexpected exception or a PHP error. Sometimes this distinction proves useful, since errors tend to be easier to fix than failures. If you have a big list of problems, it is best to tackle the errors first and see if you have any failures left when you have fixed them all.

Change the expected value in the testArrayContainsAnElement() test from 1 to 0 and the test will fail. The following example shows how PHPUnit reports this failure:

$ phpunit ArrayTest
PHPUnit 2.3.0 by Sebastian Bergmann.

.F

Time: 0.001147
There was 1 failure:
1) testArrayContainsAnElement(ArrayTest)
expected same: <0> was not: <1>
/home/sb/ArrayTest.php:21

FAILURES!!!
Tests run: 2, Failures: 1, Errors: 0, Incomplete Tests: 0.

The report shows where the failure occurs in the test code: in the test method testArrayContainsAnElement() of the test case class ArrayTest, in line 21 of the /home/sb/ArrayTest.php test code source file.

Pages: 1, 2

Next Pagearrow




Valuable Online Certification Training

Online Certification for Your Career
Earn a Certificate for Professional Development from the University of Illinois Office of Continuing Education upon completion of each online certificate program.

PHP/SQL Programming Certificate — The PHP/SQL Programming Certificate series is comprised of four courses covering beginning to advanced PHP programming, beginning to advanced database programming using the SQL language, database theory, and integrated Web 2.0 programming using PHP and SQL on the Unix/Linux mySQL platform.

Enroll today!


Sponsored by: