PHPUnit 3.3.11

Sebastian Bergmann » 25 January 2009 » in Announcements » 0 Comments

  • Fixed #670: XML configuration file ignored when executing single test case. [4538]
  • Fixed #677: PHPUnit_Extensions_SeleniumTestCase::__construct() does not forward all arguments. [4507]
  • Fixed #678: Implementation of PHPUNIT_SELENIUM_TEST_ID cookie deletion is wrong. [4519]
  • Fixed #683: Make code coverage report valid HTML. [4548]
  • Fixed #684: Unable to find test class when no test method exists. [4553]
  • Fixed an E_NOTICE on Windows because LC_MESSAGES is not defined. [4498]
Defined tags for this entry: ,

The Cost of Test Isolation - Follow-Up

Sebastian Bergmann » 18 January 2009 » in Articles » 0 Comments

This is a follow-up to "The Cost of Test Isolation (and other PHPUnit Features)".

Since the previous posting, I have added a backup/restore mechanism for static attributes of classes to PHPUnit. This is yet another feature of PHPUnit that makes the testing of code that uses global state (which includes, but is not limited to, global and superglobal variables as well as static attributes of classes) easier.

The following profiling graph illustrates the performance penalty incurred by this feature on the test execution.

Profiling PHPUnit with Xdebug

The following profiling graph was generated for an execution of PHPUnit with the --no-syntax-check --no-globals-backup --no-static-backup switches that disable these features (and also the syntac check of test code).

Profiling PHPUnit with Xdebug

My recommendation is: disable the backup/restore mechanism of globals and static attributes of classes. Not only because this greatly reduces the time required to run the tests. It also exposes tests, and thus the tested code, that interacts with global state. If, and only if, this interaction with global state cannot be avoided you can select the tests for which the backup/restore mechanism(s) should be enabled in a fine-grained way.

If you are interested in the problems associated with code that interacts with global state, especially with regard to testing it, join me for my "Untestable Code session at the php|tek 2009 conference in Chicago, IL, US in May.

Defined tags for this entry: , , , ,

PHPUnit 3.3.10

Sebastian Bergmann » 13 January 2009 » in Announcements » 0 Comments

  • Implemented #671: Allow constants as values for php.ini settings set via the XML configuration file. [4455]
  • Fixed #667: PHPUnit_Framework_Assert::getStaticAttribute() does not work for properties with NULL value. [4432]
  • Fixed #668: Directory separator needs to be escaped in YUI panel data. [4447]
Defined tags for this entry: ,

Cool PHP Objects Sleep on the Couch

Sebastian Bergmann » 11 January 2009 » in New Features » 0 Comments

The Object_Freezer library for PHP provides the low-level functionality to store ("freeze") and fetch ("thaw") any PHP userland object to and from arbitrary object stores.

Today I added an object storage implementation that uses Apache CouchDB as its backend.

Apache CouchDB, the distributed, fault-tolerant and schema-free document-oriented database that provides scalability as a consequence of its design, is a natural fit for such an object store.

The following example shows how the Object_Freezer's new backend for CouchDB can be used to persist PHP objects:

<?php
require 'Object/Freezer/Storage/CouchDB.php';
 
class Foo
{
    public $a;
    protected $b;
    private $c;
 
    public function __construct($a, $b, $c)
    {
        $this->a = $a;
        $this->b = $b;
        $this->c = $c;
    }
}
 
$object = new Foo(1, 2, 3);
var_dump($object);
 
// Store the object in the database "test" of the
// CouchDB server that is running on localhost:5984.
$storage = new Object_Freezer_Storage_CouchDB('test');
$storage->store($object);
 
// Freezing the object added the "magic" attributes
// __php_object_freezer_uuid and __php_object_freezer_hash.
var_dump($object);
 
// Fetch the object (by ID) from the database.
var_dump($storage->fetch($object->__php_object_freezer_uuid));
?>

Below is the output produced by the script above:

object(Foo)#1 (3) {
  ["a"]=>
  int(1)
  ["b":protected]=>
  int(2)
  ["c":"Foo":private]=>
  int(3)
}

object(Foo)#1 (5) {
  ["a"]=>
  int(1)
  ["b":protected]=>
  int(2)
  ["c":"Foo":private]=>
  int(3)
  ["__php_object_freezer_uuid"]=>
  string(36) "8d17b95e-1410-4e54-a70c-064c09c79210"
  ["__php_object_freezer_hash"]=>
  string(40) "40cd89ec4ea3b5a1c1419c83b4ea643da5341ab8"
}

object(Foo)#10 (5) {
  ["a"]=>
  int(1)
  ["b":protected]=>
  int(2)
  ["c":"Foo":private]=>
  int(3)
  ["__php_object_freezer_uuid"]=>
  string(36) "8d17b95e-1410-4e54-a70c-064c09c79210"
  ["__php_object_freezer_hash"]=>
  string(40) "40cd89ec4ea3b5a1c1419c83b4ea643da5341ab8"
}

Here is an overview of the current feature set:

  • PHP objects, with the exception of objects of "special" classes such as Closure or PDO, can be frozen and thawed.
  • Graphs of objects, including those that contain circular references, are supported.
  • Frozen objects can be stored in and fetched from an Apache CouchDB database.
Defined tags for this entry: , ,

Speaking at php|tek 2009

Sebastian Bergmann » 09 January 2009 » in Events » 0 Comments

I will present a session at the php|tek 2009 conference:

Untestable Code

How do you write untestable code and anger an ancient goddess?

These and other questions will guide us while we discuss testability, an often forgotten attribute of software design and quality.

Starting from untestable code fragments, the audience will learn why the code is untestable and how it can be refactored for testability.

Together with my partners Arne Blankerts and Stefan Priebsch, I will co-present the following workshop:

PHP Code Review

In this workshop, three PHP experts with different software engineering focuses (testing, architecture, and security) will perform an interactive code review together with the audience.

Attendees of this lab will learn how experts look at code what good code and bad code looks like, and how to avoid the most common gotchas. They are invited to bring their own code for an anonymous code review for an increased benefit from the workshop.

See you in Chicago in May!

Defined tags for this entry: ,

Speaking at PHP UK Conference 2009

Sebastian Bergmann » 09 January 2009 » in Events » 0 Comments

I will present a session at the PHP UK Conference 2009:

Of Lambda Functions, Closures and Traits

Lambda Functions and Closures allow the quick definition of throw-away functions (for use with array_map(), for instance) that are not used elsewhere.

Traits reduce some limitations of single inheritance by enabling the reuse method sets freely in several independent classes.

This session introduces the audience to the implementation of lambda functions, closures, and functors (which are new in PHP 5.3) as well as traits (which will be added in PHP 6).

See you in London in February!

Defined tags for this entry: ,