PHPUnit 3.5: Refactoring to Components

Sebastian Bergmann » 23 July 2010 » in Articles » 0 Comments

When you look at the list of changes for PHPUnit 3.5, you will see that many of them deal with refactoring to components. Here is an overview of these new components:

  • PHP_CodeCoverage

    The collection, processing, and rendering of code coverage information has been factored out into a separate component. A bit more information can be found here.

  • PHPUnit_MockObject

    The functionality to automatically generate an object that can act as a test double for a specified original class has been factored out into a separate component. Do not worry, getMock() and related methods will work just as they did in previous versions of PHPUnit. The refactoring, however, makes the usage of other mock object libraries (such as Mockery or Phake, for instance) easier.

  • DbUnit

    The database testing functionality that is provided by the DbUnit extension and the respective DatabaseTestCase class has been moved to a separate component. Michael Lively Jr, the author of DbUnit, is now able to make releases of the database testing extension on a release schedule that is separate from PHPUnit itself, meaning that I will be even less involved in its development than I have before.

  • PHPUnit_Selenium

    SeleniumTestCase, the Selenium RC integration for PHPUnit, has been moved to a separate component to allow a release cycle separate from PHPUnit itself.

  • File_Iterator, PHP_Timer, Text_Template

    Utility methods to collect files and report resource usage as well as a simple templating mechanism have been moved to separate components so that they can be reused by other tools such as phpcb, phpcs, phpcpd, and pdepend.

Defined tags for this entry:

Using PHPUnit from a Git Checkout

Sebastian Bergmann » 15 April 2010 » in Articles » 3 Comments

Users of PHPUnit frequently ask me questions such as "How do I use PHPUnit from a Git checkout?" or "How do I run PHPUnit's own test suite?" This article provides the answers to these questions.

Getting PHPUnit from Git

sb@thinkpad ~ % git clone git://github.com/sebastianbergmann/phpunit.git

You now have a phpunit directory in your current working directory that contains the branch for PHPUnit 3.5 (at the time of writing) because the 3.5 branch is currently configured as the default branch for the PHPUnit repository on GitHub. If you want to switch to the branch for PHPUnit 3.4, for instance, you can use

sb@thinkpad phpunit % git checkout -b 3.4 origin/3.4

This tells Git to create a new local branch of name 3.4 (-b 3.4) that is set up to track the remote branch 3.4 from origin (origin/3.4). Git automatically switches to the newly created local branch. Using

sb@thinkpad phpunit % git checkout 3.5

you can switch back to the branch for PHPUnit 3.5.

Running PHPUnit from a Git checkout

Inside the phpunit directory you will find the phpunit.php script. Using this script you can invoke the PHPUnit TextUI test runner:

sb@thinkpad ~ % phpunit/phpunit.php
PHPUnit @package_version@ by Sebastian Bergmann.
.
.
.

The @package_version@ placeholder string for the version information makes it clear that a non-release version of PHPUnit is being used. Upon installation, the PEAR Installer replaces this placeholder string with the relevant information.

Running PHPUnit's Own Test Suite

Running PHPUnit's own test suite is as easy as invoking phpunit in the checkout directory:

sb@thinkpad phpunit % phpunit                  
PHPUnit @package_version@ by Sebastian Bergmann.

............................................................  60 / 681
............................................................ 120 / 681
............................................................ 180 / 681
............................................................ 240 / 681
............................................................ 300 / 681
............................................................ 360 / 681
............................................................ 420 / 681
............................................................ 480 / 681
................................SSSSSSSSSSSSSSSSSSSSSSSSSSSS 540 / 681
SSSS.......................................S................ 600 / 681
............................................................ 660 / 681
.....................

Time: 27 seconds, Memory: 56.25Mb

OK, but incomplete or skipped tests!
Tests: 681, Assertions: 1459, Skipped: 33.

Writing code coverage data to XML file, this may take a moment.

Generating code coverage report, this may take a moment.

The above works because there is an XML configuration for PHPUnit (phpunit.xml.dist) in the directory that contains information about which tests to run and what logfiles to produce.

Defined tags for this entry: ,

Stubbing Hard-Coded Dependencies

Sebastian Bergmann » 16 February 2010 » in Articles » 1 Comment

This article is part of a series on testing untestable code:

In a unit test, mock objects can simulate the behavior of complex, real (non-mock) objects and are therefore useful when a real object is difficult or impossible to incorporate into a unit test.

A mock object can be used anywhere in the program where the program expects an object of the mocked class. However, this only works as long as the object can be passed into the context where the original object is used.

Consider the following example:

<?php
require_once 'Bar.php';
 
class Foo
{
    public function doSomething()
    {
        // ...
 
        $bar = new Bar;
        $bar->doSomethingElse();
 
        // ...
 
        return TRUE;
    }
}
?>
<?php
class Bar
{
    public function doSomethingElse()
    {
        print '*';
    }
}
?>

With the code above, it is impossible to run a unit test for the Foo::doSomething() method without also creating an object of Bar. As the method creates the object of Bar itself, we cannot inject a mock object in its stead.

In a perfect world, code such as the above could be refactored using Dependency Injection:

<?php
require_once 'Bar.php';
 
class Foo
{
    public function doSomething(Bar $bar = NULL)
    {
        if ($bar === NULL) {
            $bar = new Bar;
        }
 
        // ...
 
        $bar->doSomethingElse();
 
        // ...
 
        return TRUE;
    }
}
?>

Unfortunately, this is not always possible (not because of technical reasons, though).

This is where the set_new_overload() function that is provided by the test_helpers extension for the PHP Interpreter comes into play. It can be used to register a callback that is automatically invoked when the new operator is executed:

<?php
require_once 'Foo.php';
 
class FooTest extends PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        $this->getMock(
          'Bar',                    /* name of class to mock     */
          array('doSomethingElse'), /* list of methods to mock   */
          array(),                  /* constructor arguments     */
          'BarMock'                 /* name for mocked class     */
        );
 
        set_new_overload(array($this, 'newCallback'));
    }
 
    protected function tearDown()
    {
        unset_new_overload();
    }
 
    protected function newCallback($className)
    {
        switch ($className) {
            case 'Bar': return 'BarMock';
            default:    return $className;
        }
    }
 
    public function testDoSomething()
    {
        $foo = new Foo;
        $this->assertTrue($foo->doSomething());
    }
}
?>

Lets run this unit test:

PHPUnit 3.4.10 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 7.50Mb

OK (1 test, 2 assertions)

Note that there is no * (printed from Bar::doSomethingElse()) in the output above.

Defined tags for this entry: ,

Sharing Fixture Between Tests

Sebastian Bergmann » 14 February 2010 » in New Features » 6 Comments

There are few good reasons to share fixtures between tests, but in most cases the need to share a fixture between tests stems from an unresolved design problem.

A good example of a fixture that makes sense to share across several tests is a database connection: you log into the database once and reuse the database connection instead of creating a new connection for each test. This makes your tests run faster.

PHPUnit 3.5 removes the fixture sharing feature of the TestSuite class. It was tedious to use this feature as it required the usage of a custom TestSuite class in addition to the test case class. Furthermore, its implementation was a "hack".

PHPUnit 3.4 introduced the setUpBeforeClass() and tearDownAfterClass() template methods that can be used in a test case class. These methods allow a much cleaner and simpler implementation of fixture sharing between tests of the same test case class:

<?php
class DatabaseTest extends PHPUnit_Framework_TestCase
{
    protected static $dbh;
 
    public static function setUpBeforeClass()
    {
        self::$dbh = new PDO('sqlite::memory:');
    }
 
    public static function tearDownAfterClass()
    {
        self::$dbh = NULL;
    }
}
?>

The example above uses the setUpBeforeClass() and tearDownAfterClass() template methods to connect to the database before the test case class' first test and to disconnect from the database after the last test of the test case, respectively.

It cannot be emphasized enough that sharing fixtures between tests reduces the value of the tests. The underlying design problem is that objects are not loosely coupled. You will achieve better results solving the underlying design problem and then writing tests using test doubles, than by creating dependencies between tests at runtime and ignoring the opportunity to improve your design.

Defined tags for this entry: ,

Stubbing and Mocking Static Methods

Sebastian Bergmann » 12 February 2010 » in New Features » 4 Comments

This article is part of a series on testing untestable code:

With PHPUnit 3.5 it will be possible to stub and mock static methods.

Consider the class Foo:

<?php
class Foo
{
    public static function doSomething()
    {
        return static::helper();
    }
 
    public static function helper()
    {
        return 'foo';
    }
}
?>

When testing Foo::doSomething() we want to decouple it from its dependency Foo::helper(). With PHPUnit 3.5 and PHP 5.3 as well as consistent use of late static binding (using static:: instead of self::) the following is possible:

<?php
class FooTest extends PHPUnit_Framework_TestCase
{
    public function testDoSomething()
    {
        $class = $this->getMockClass(
          'Foo',          /* name of class to mock     */
          array('helper') /* list of methods to mock   */
        );
 
        $class::staticExpects($this->any())
              ->method('helper')
              ->will($this->returnValue('bar'));
 
        $this->assertEquals(
          'bar',
          $class::doSomething()
        );
    }
}
?>

The new staticExpects() method works similar to the non-static expects() variant.

This approach only works for the stubbing and mocking of static method calls where caller and callee are in the same class. This is because static methods are death to testability:

"Unit-Testing needs seams, seams is where we prevent the execution of normal code path and is how we achieve isolation of the class under test. Seams work through polymorphism, we override/implement class/interface and then wire the class under test differently in order to take control of the execution flow. With static methods there is nothing to override. Yes, static methods are easy to call, but if the static method calls another static method there is no way to override the called method dependency."
Defined tags for this entry: , ,