PHPBuilder - Use PHPUnit to Implement Unit Testing in Your PHP Development



RSS Twitter
Articles Tools

Use PHPUnit to Implement Unit Testing in Your PHP Development

by: W. Jason Gilmore
|
May 26, 2010

Creating powerful modern websites is about so much more than simply slinging code. The complexity has become such that most gainfully employed web developers no longer create websites because the connotation is a website is a bunch of hastily slapped together "pages." Instead, we are creating web applications, with one important difference between the two being that the latter are built using a rigorous process, and with that, a rigorous testing program.
If you create web applications that talk to databases, process user input, integrate Ajax functionality, and perform other mission-critical tasks, then it's crucial that you institute a rigorous testing program -- alongside other procedures that may already be in place, such as coding standards and documentation. The PHP community has long had a great testing utility at their disposal known as PHPUnit, and in this tutorial I offer a brief introduction to its benefits.

Installing PHPUnit

PHPUnit is available as a PEAR package, meaning you can install it by simply executing the following two commands:
%>pear channel-discover pear.phpunit.de
%>pear install phpunit/PHPUnit
The above should work as written if you run Windows, however if like me you run a Linux distribution such as Ubuntu, then you'll of course need to preface these commands with sudo.
Once installed, it's time to write our first test!

Writing Your First Unit Test

A strategy known as unit testing involves writing a series tests. Each test is intended to validate the intent of a specific bit, or unit, of application code. Within these tests you make various assertions confirming whether the outcome meets expectations.
As an example, suppose you were tasked with creating a PHP application that processed Docbook files, parsing the documents to retrieve information such as the document title and author. Because of the often mind-bending nature of regular expressions, make sure that your code is thoroughly tested in order to uncover any unexpected issues. A simplified version of such a class might look like this:
<?php

class Chapter {

  private $_file;
  private $_title;

  ...

  public function setTitle()
  {

    $pattern = "/<title>(.*?)<\/title>/";
    preg_match($pattern, $this->_file, $matches);

    $this->_title = $matches[1];

  }

?>
To test the Chapter class' setTitle() method, you should make sure that the string found between the <title> tags matches your expectation. You do this by making an assertion within an aptly-named class that extends PHPUnit's PHPUnit_Framework_TestCase class:
<?php

include "../src/Chapter.php";

class ChapterTest extends PHPUnit_Framework_TestCase
{

    protected $_chapter = null;

    public function testTitleMatchesWhenOneTitleInstanceFoundInString()
    {
        
        $docbook = "<docbook><title>Physics 101</title></docbook>";
        $this->_chapter = new Chapter();
        $this->_chapter->setFile($docbook);
        $this->_chapter->setTitle();
        $this->assertEquals($this->_chapter->getTitle(), "Physics 101");

    }

}

?>
There are several important matters to note regarding this example:
  • In a real-world example you should include your class files on PHP's include_path in order to maintain maximum test portability
  • The test method name must begin with the word test. Although after that you're free to name the test anything you please, I suggest using long, explanatory names as I've done here (you'll see why later in the article).
  • The assertEquals() method compares two provided values for equality. We know the title should be Physics 101 and so compare that value with that returned by the Chapter object's getTitle() method.
If the assertion passes, then so will the test. Otherwise it will fail. We can verify the test outcome by navigating to the test's folder and executing the following command:
%>phpunit ChapterTest.php
PHPUnit 3.4.12 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 3.50Mb

OK (1 test, 1 assertion)
That dot signifies passage of a test. As your test class expands to include other methods, you'll strive to string those dots together. If a test fails, an F will appear in place of the dot. For instance, if you change the asserted title Physics 101 to Math 254 and run the test again, you'll be greeted with the following output:
PHPUnit 3.4.12 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 3.50Mb

There was 1 failure:

1) ChapterTest::testTitleMatchesWhenOneTitleInstanceFoundInString
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-Physics 101
+Math 254

/home/wjgilmore/phpunit/code/tests/ChapterTest.php:17

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

1
|
2
Next Page »

Comment and Contribute

Your comment has been submitted and is pending approval.

Author:
W. Jason Gilmore

Comment:



Comment:

(Maximum characters: 1200). You have characters left.