PHPUnit 3.5: Less $this Required

Sebastian Bergmann » 16 August 2010 » in New Features » 31 Comments

The feature discussed below has been removed from PHPUnit due to community feedback.

Over the years, I have gotten quite a few "complaints" from PHPUnit users that they do not like typing $this-> as often as they have to:

<?php
class StackTest extends PHPUnit_Framework_TestCase
{
    public function testPushAndPop()
    {
        $stack = array();
        $this->assertEquals(0, count($stack));
 
        array_push($stack, 'foo');
        $this->assertEquals('foo', $stack[count($stack)-1]);
        $this->assertEquals(1, count($stack));
 
        $this->assertEquals('foo', array_pop($stack));
        $this->assertEquals(0, count($stack));
    }
}
?>

As of PHPUnit 3.5, they can write test code that requires less $this-> statements:

<?php
require_once 'PHPUnit/Framework/Assert/Functions.php';
 
class StackTest extends PHPUnit_Framework_TestCase
{
    public function testPushAndPop()
    {
        $stack = array();
        assertEquals(0, count($stack));
 
        array_push($stack, 'foo');
        assertEquals('foo', $stack[count($stack)-1]);
        assertEquals(1, count($stack));
 
        assertEquals('foo', array_pop($stack));
        assertEquals(0, count($stack));
    }
}
?>

Here's hoping that this makes some people happy :-)

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: , ,

CRAP in PHPUnit 3.5

Sebastian Bergmann » 12 January 2010 » in New Features » 6 Comments

For the upcoming PHPUnit 3.5, I have factored out all code that is related to code coverage and put it into a separate component: PHP_CodeCoverage.

PHP_CodeCoverage is a component that provides collection, processing, and rendering functionality for PHP code coverage information. It makes PHPUnit's mature code coverage functionality available outside of PHPUnit.

Having all code that deals with code coverage in a separate component allows for easier development and better testing. The first result of these improved development conditions is a small new feature that I recently implemented, the support for the CRAP metric.

From crap4j.org:

The CRAP (Change Risk Analysis and Predictions) software metric [has] a mildly offensive metric name [and helps] to help protect you from truly offensive code.

The CRAP metric combines cyclomatic complexity and code coverage from automated tests (e.g. [PHPUnit] tests) to help you identify code that might be particularly difficult to understand, test, or maintain — the kind of code that makes developers say: “This is crap!” or, if they are stuck maintaining it, “Oh, crap!”.

The screenshot below shows how the CRAP metric is reported in the HTML code coverage report:

Code Coverage Report
Defined tags for this entry: , ,

Fixture Reuse in PHPUnit 3.4

Sebastian Bergmann » 25 February 2009 » in New Features » 1 Comment

As mentioned earlier, PHPUnit 3.4 adds support for Test Dependencies as introduced by Kuhn et. al. in JExample: Exploiting Dependencies Between Tests to Improve Defect Localization.

Today I implemented fixture reuse based on test dependency information:

<?php
class StackTest extends PHPUnit_Framework_TestCase
{
    public function testPush()
    {
        $stack = array();
        $this->assertEquals(0, count($stack));
 
        array_push($stack, 'foo');
        $this->assertEquals('foo', $stack[count($stack)-1]);
        $this->assertEquals(1, count($stack));
 
        return $stack;
    }
 
    /**
     * @depends testPush
     */
    public function testPop(array $stack)
    {
        $this->assertEquals('foo', array_pop($stack));
        $this->assertEquals(0, count($stack));
    }
}
?>

Just like JExample, PHPUnit 3.4 introduces producer-consumer relationships to unit-testing.

  • A producer is a test method that yields its unit under test as return value.
  • A consumer is a test method that depends on one or more producers and their return values.

PHPUnit 3.4 skips any test method whose producer has failed and the return value of a producer is injected into its consumers.

Defined tags for this entry: , , ,