Planet PHPUnit

February 16, 2010

Sebastian Bergmann

Stubbing Hard-Coded Dependencies

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.

February 14, 2010

Sebastian Bergmann

Sharing Fixture Between Tests

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.

February 12, 2010

Sebastian Bergmann

Stubbing and Mocking Static Methods

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."

February 11, 2010

Sebastian Bergmann

Testing Code That Uses Singletons

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

I frequently quote Miško Hevery with

"It is hard to test code that uses singletons."

And then my audience asks me ...

Why is it hard to test code that uses singletons?

Lets have a look at the default implementation of the Singleton design pattern in PHP:

<?php
class Singleton
{
    private static $uniqueInstance = NULL;
 
    protected function __construct() {}
    private final function __clone() {}
 
    public static function getInstance()
    {
        if (self::$uniqueInstance === NULL) {
            self::$uniqueInstance = new Singleton;
        }
 
        return self::$uniqueInstance;
    }
}
?>

The code above declares a class that cannot be instantiated (or cloned) by a client using the new (or clone) operator(s). To get a reference to the only instance of the class one has to use the static method getInstance(). Usually the code that uses the Singleton (which we will refer to as client) is strongly coupled to the getInstance() method:

<?php
class Client
{
    public function doSomething()
    {
        $singleton = Singleton::getInstance();
 
        // ...
    }
}
?>

It is impossible to write a test for the doSomething() method without also invoking the singleton's getInstance() method. This means that we cannot get a fresh instance of the Singleton class and thus have no guarantee that there are no side effects in multiple tests that interact with the singleton.

Dependency Injection

Dependency Injection can help with decoupling the client from the getInstance() method:

<?php
class Client
{
    public function doSomething(Singleton $singleton = NULL)
    {
        if ($singleton === NULL) {
            $singleton = Singleton::getInstance();
        }
 
        // ...
    }
}
?>

Instead of unconditionally invoking the getInstance() method inside the doSomething() we can now optionally pass in an instance of the Singleton class. This allows us to pass in a test-specific equivalent such as a mock object or stub:

<?php
class ClientTest extends PHPUnit_Framework_TestCase
{
    public function testSingleton()
    {
        $singleton = $this->getMock(
          'Singleton', /* name of class to mock     */
          array(),     /* list of methods to mock   */
          array(),     /* constructor arguments     */
          '',          /* name for mocked class     */
          FALSE        /* do not invoke constructor */
        );
 
        // ... configure $singleton ...
 
        $client = new Client;
        $client->doSomething($singleton);
 
        // ...
    }
}
?>

Alternative Singleton Implementations

Either as an alternative or in addition to rewriting the clients to optionally accept an instance of the Singleton class as an argument, we can also rewrite the Singleton class to make testing easier.

Resettable Singleton

The first approach is to add a reset() method to the Singleton class:

<?php
class Singleton
{
    private static $uniqueInstance = NULL;
 
    protected function __construct() {}
    private final function __clone() {}
 
    public static function getInstance()
    {
        if (self::$uniqueInstance === NULL) {
            self::$uniqueInstance = new Singleton;
        }
 
        return self::$uniqueInstance;
    }
 
    public static function reset() {
        self::$uniqueInstance = NULL;
    }
}
?>

Invoking the reset() method causes the getInstance() method to create a fresh object of the Singleton class the next time it is called.

Singleton with Test Context

The second approach is to add a testing context to the Singleton class:

<?php
class Singleton
{
    private static $uniqueInstance = NULL;
    public static $testing = FALSE;
 
    protected function __construct() {}
    private final function __clone() {}
 
    public static function getInstance()
    {
        if (self::$uniqueInstance === NULL ||
            self::$testing) {
            self::$uniqueInstance = new Singleton;
        }
 
        return self::$uniqueInstance;
    }
}
?>

Setting Singleton::$testing = TRUE; causes the getInstance() method to create a fresh object of the Singleton class each time it is called.

PHPUnit Can Help, Too

PHPUnit has a backup/restore mechanism for static attributes of classes.

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.

Just Because You Can, Does Not Mean You Should

Yes, it is possible write testable code that uses singletons.
This does not mean, however, that you should use them without thinking twice.

February 09, 2010

Sebastian Bergmann

Testing Your Privates

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

No, not those privates. If you need help with those, this book might help.

One question I get over and over again when talking about Unit Testing is this:

"How do I test the private attributes and methods of my objects?"

Lets assume we have a class Foo:

<?php
class Foo
{
    private $bar = 'baz';
 
    public function doSomething()
    {
        return $this->bar = $this->doSomethingPrivate();
    }
 
    private function doSomethingPrivate()
    {
        return 'blah';
    }
}
?>

Before we explore how protected and private attributes and methods can be tested directly, lets have a look at how they can be tested indirectly.

The following test calls the testDoSomething() method which in turn calls the doSomethingPrivate() method:

<?php
class FooTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo::doSomething
     * @covers Foo::doSomethingPrivate
     */
    public function testDoSomething()
    {
        $foo = new Foo;
        $this->assertEquals('blah', $foo->doSomething());
    }
}
?>

The test above assumes that testDoSomething() only works correctly when testDoSomethingPrivate() works correctly. This means that we have indirectly tested testDoSomethingPrivate(). The problem with this approach is that when the test fails we do not know directly where the root cause for the failure is. It could be in either testDoSomething() or testDoSomethingPrivate(). This makes the test less valuable.

PHPUnit supports reading protected and private attributes through the PHPUnit_Framework_Assert::readAttribute() method. Convenience wrappers such as PHPUnit_Framework_TestCase::assertAttributeEquals() exist to express assertions on protected and private attributes:

<?php
class FooTest extends PHPUnit_Framework_TestCase
{
    public function testPrivateAttribute()
    {
        $this->assertAttributeEquals(
          'baz',  /* expected value */
          'bar',  /* attribute name */
          new Foo /* object         */
        );
    }
}
?>

PHP 5.3.2 introduces the ReflectionMethod::setAccessible() method to allow the invocation of protected and private methods through the Reflection API:

<?php
class FooTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo::doSomethingPrivate
     */
    public function testPrivateMethod()
    {
        $method = new ReflectionMethod(
          'Foo', 'doSomethingPrivate'
        );
 
        $method->setAccessible(TRUE);
 
        $this->assertEquals(
          'blah', $method->invoke(new Foo)
        );
    }
}
?>

In the test above we directly test testDoSomethingPrivate(). When it fails we immediately know where to look for the root cause.

I agree with Dave Thomas and Andy Hunt, who write in their book "Pragmatic Unit Testing":

"In general, you don't want to break any encapsulation for the sake of testing (or as Mom used to say, "don't expose your privates!"). Most of the time, you should be able to test a class by exercising its public methods. If there is significant functionality that is hidden behind private or protected access, that might be a warning sign that there's another class in there struggling to get out."

So: Just because the testing of protected and private attributes and methods is possible does not mean that this is a "good thing".

January 31, 2010

Manuel Pichler

phpUnderControl 0.5.1 released

Today I have released phpUnderControl version 0.5.1. It's a bug fix release that closes several issues open since a long time. First of all I would like to thank Sebastian Marek who was the main contributor to this releases, so a big thankyou to you.

  • Now phpUnderControl should work with CruiseControl 2.8.3. Thanks to Mike van Riel who provided some hints on this issue in a blog comment.
  • Fixed #983: Graph unitests throw fatal error when ezComponents not available.
  • Fixed #966: phpcs-details.xsl not showing file name.
  • Closed #863: Destination option is now deprecated.
  • Fixed #862: Command line switches without parameter don't work.
  • Fixed #861: Password is used as username in check outs. This patch was supplied by Thorsten Daners via e-mail.
  • Fixed #734: Now the build dropdown redirects to the correct build uri.
  • Implemented #703: PHPUnit test results are now the first entry on the project overview page.
  • Fixed #700: Throw an exception when the specified project does not exist.
  • Implemented #675: Use "php -l" for lint checking and not PHPUnit.
  • Implemented #625: Integrate PHP_Depend results.

Beside the new release some more things have changed. From now on the phpUnderControl development is hosted on github. This means that from now on the latest version of phpUnderControl can be obtained with the following command:

mapi@arwen ~ $ git clone \
               git://github.com/manuelpichler/phpUnderControl.git

Additionally we have moved the phpUnderControl's PEAR Channel Server from pear.phpunit.de to its own server pear.phpundercontrol.org. At this point I would like to thank Sebastian for providing phpUnderControl's infrastructure under the PHPUnit umbrella for the last three years.

mapi@arwen ~ $ pear uninstall phpunit/phpUnderControl
mapi@arwen ~ $ pear channel-discover pear.phpundercontrol.org
mapi@arwen ~ $ pear install --alldeps phpuc/phpUnderControl-beta
Starting to download phpUnderControl-0.5.1.tgz (539,717 bytes)
..........................................done: 539,717 bytes
install ok: channel://pear.phpundercontrol.org/phpUnderControl-0.5.1

January 12, 2010

Sebastian Bergmann

CRAP in PHPUnit 3.5

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

December 26, 2009

Sebastian Bergmann

PHPUnit Development Moved to GitHub

Over the Christmas holidays I took a break from translating and editing the book on quality assurance in PHP projects that I am working on to finally migrate the code repository of PHPUnit from a self-hosted Subversion repository to a Git repository that is hosted on GitHub.

How did I get here?

I was staying at Arjen's place in Brisbane in August 2008 and one day we talked about distributed version control. Although I knew the basic concepts behind it, I was not yet convinced enough to take the plunge and try it out. Our discussion changed that, but it was not until my second trip to Australia later that year that I took the initial code for PHP_ObjectFreezer (which I had on my laptop since I started to hack on it together with Stefan on the flight to Atlanta for php|works 2008) and put it into a bzr repository on Launchpad. I grew comfortable enough with bzr quickly, but never really warmed up to Launchpad.

Around that time, I was hearing more and more positive things about Git and GitHub from my peers. So I took the PHP_ObjectFreezer code base and migrated it to Git and hosted the repository and GitHub to experiment with both the tool and the platform. It was a step that I did not regret and all the projects that I started since then are hosted on GitHub: bytekit-cli, phpcpd, phpdcd, phploc, PHP_CodeCoverage, PHP_FileIterator, PHP_ObjectFreezer, Text_Template, PHP_TokenStream.

Why did I do this?

Let me start with a quote from GitHub.com:

  • Git is a fast, efficient, distributed version control system ideal for the collaborative development of software.
  • GitHub is the easiest (and prettiest) way to participate in that collaboration: fork projects, send pull requests, monitor development, all with ease.

Over the last year, I have come to appreciate Git and GitHub a lot and also wanted to use them for PHPUnit.

Sure, I could have used git-svn for bi-directional operation between the existing Subversion repository and Git, but this would have always felt like only going half the way.

The arguments in favour of distributed version control systems are discussed by others far better than I could discuss them here, so I will just quote Ian Clatworthy's paper on distributed version control systems, in which discusses not only the technical differences between traditional version control systems and distributed version control systems, but also the differences with regard to development workflows and developer interaction:

  • Developers can collaborate directly without needing central authority or incurring central administration overhead
  • Developers can still be productive when the umbilical cord to their central VCS repository is broken, e.g. when travelling.
  • Creating and destroying branches are simple operations. This is particularly useful when experimenting with new ideas, e.g. a spike when using eXtreme Programming.
  • Ad-hoc collaboration with peers [is facilitated by] intelligent merge tracking [because] merging early and merging often is both possible and surprisingly unpainful. It is difficult to explain just how much of an impact this can make on how co-developers can work together more easily, e.g. when Pair Programming.

What does this mean for you?

PHPUnit is now hosted on GitHub.

In a nutshell, this means that the development of PHPUnit is now more open than it was before. If you want to contribute, you just need to fork PHPUnit on GitHub and create a topic branch for your contribution. Then let me know about your topic branch and I may or may not merge it.

If you are currently using svn:externals to pull PHPUnit into your own Subversion repository, you need to think about an alternative as PHPUnit's Subversion repository is no longer updated and will eventually go away.

How did I do it?

As this might be of interest to someone who wants to migrate his/her repository from Subversion to Git, here is how I performed the migration.

I started by creating a local mirror of the Subversion repository:

# Fetch Subversion repository
svnadmin create phpunit.svn
 
cat 'EOF' > phpunit.svn/hooks/pre-revprop-change
#!/bin/sh
USER="$3"
 
if [ "$USER" = "svnsync" ]; then exit 0; fi
 
echo "Only the svnsync user can change revprops" >&2
exit 1
EOF
 
chmod +x phpunit.svn/hooks/pre-revprop-change
 
svnsync init \
  --username svnsync \
  file://`pwd`/phpunit.svn \
  svn://svn.phpunit.de/phpunit
 
svnsync sync \
  --username svnsync \
  file://`pwd`/phpunit.svn

Then I used svn2git for the actual migration:

# Create directory for Git repository
mkdir phpunit.git && cd phpunit.git
 
# Use svn2git to import repository
svn2git \
  --trunk trunk \
  --branches branches/release \
  --tags tags \
  --authors /home/sb/authors.txt \
  file:///home/sb/phpunit.svn/phpunit

After that I had to delete quite a few superfluous branches and tags, but that quickly dealt with. The final step was to create common ancestors for the master, 3.5, and 3.4 branches so that merging becomes easy and painless.

# Create 3.5 and 3.4 branches (in local repository)
git checkout remotes/origin/3.5 -b 3.5
git checkout remotes/origin/3.4 -b 3.4

# Create common ancestors for the master, 3.5, and 3.4 branches
git checkout 3.5 && git merge --strategy=ours master
git checkout 3.4 && git merge --strategy=ours 3.5

git checkout master && git merge --strategy=ours 3.5
git checkout 3.5 && git merge --strategy=ours 3.4

After that I had to delete quite a few superfluous branches and tags, but that quickly dealt with.

At this point I would like to thank David Soria Parra who helped me figure out some details here and there.

December 06, 2009

Manuel Pichler

phpUnderControl 0.5.0 released

After quite some time of silence around phpUnderControl I have bundled the 0.5.0 release today. Beside minor changes, bugfixes and enhancements this release contains one new major feature, the PHP_CodeBrowser.

phpUnderControl integrating PHP_CodeBrowser

The PHP_CodeBrowser is a separate application that collects various XML log files with different project metrics/violations and presents them in a browseable source view with syntax highligting. This tool is a contribution by the Mayflower GmbH, where it was developed and now shared with the Open Source Community. At this point I would like to thank Mayflower as a whole and in particular at Elger and Thorsten, which were responsible for all technical aspects of this contribution.

To use the PHP_CodeBrowser you must add an additional execute publisher to your CruiseControl config.xml file that generates the PHP_CodeBrowser html report and an additional artifacts publisher to move the generated PHP_CodeBrowser report into the projects artifacts directory.

<?xml version="1.0" encoding="UTF-8" ?>
<cruisecontrol>
  <!-- ... -->
  <project name="PHP_Depend" buildafterfailed="false">
    <!-- ... -->
    <publishers>
      <!-- ... -->
      <execute command="phpcb 
        --log projects/${project.name}/build/logs 
        --source projects/${project.name}/source/PHP 
        --output projects/${project.name}/build/php-code-browser"/>
      <artifactspublisher 
        dir="projects/${project.name}/build/php-code-browser" 
        dest="artifacts/${project.name}" 
        subdirectory="php-code-browser"/>
      <!-- ... -->
    </publishers>
  </project>
</cruisecontrol>

But why do we use a CruiseControl publishers instead of a regular ant (Your build tool here) target? The answer is really simple. The PHP_CodeBrowser must be the very last artifact generated for a project, which means it must also run after PHPUnit, to collect the test result logs. But in most setups PHPUnit is configured with failonerror="on" to mark a build as failed, when an error occured during the test execution. But with this configuration a following PHP_CodeBrowser target would never be executed by ant, because the build failed already. This cannot happen with a CruiseControl publisher which is always executed in a separated process.

If you create a new project with phpUnderControl's project command, phpUnderControl will automatically search for an installed PHP_CodeBrowser and add the required publishers to your config.xml file when it is present.

mapi@arwen ~ $ phpuc project \
       --project-name PHP_Depend \
       --source-dir PHP \
       --test-case PHP_Depend_AllTests \
       --test-dir tests \
       --test-file PHP/Depend/AllTests.php \
       --version-control svn \
       --version-control-url http://svn.pdepend.org/branches/0.9.0 \
       /opt/cruisecontrol/cruisecontrol-bin-2.8.2

To get the latest version of phpUnderControl, you can use the PEAR-Channel-Server:

mapi@arwen ~ $ pear channel-discover pear.phpunit.de
mapi@arwen ~ $ pear install phpunit/phpUnderControl-beta

or you can check it out from the subversion repository:

mapi@arwen ~ $ svn co svn://phpunit.de/phpunit/phpUnderControl/trunk

November 04, 2009

Quality Assurance in PHP Projects

Update

It has been quiet on this website since we posted the last contributed chapter abstract in June and it is time to give you an update. But first, allow me to refresh your memory on the list of contributed chapters:
As we only have a deadline for the German edition so far and since we received the majority of contributed chapters in English, Stefan and I are currently busy translating the contributed chapters from English to German in an effort to meet our deadline. We are currently looking at a release date for the German edition in late spring / early summer of 2010.

Once we have finished the manuscript for the German edition, we will start working on the manuscript for the English edition. Hopefully, this process will be much faster as we only need to translate a couple of chapters from German to English. We are hopeful that the English edition will be available not much later than the German edition.

October 25, 2009

Sebastian Bergmann

PHPUnit 3.4.2

I have released PHPUnit 3.4.2 today.

Besides the usual bug fixes, this release disables the backup and restore operations for static attributes (that was introduced in PHPUnit 3.4.0) by default.

The previous default setting caused too many problems with existing test suites (problems that would have been recognized earlier had users actually tested the PHPUnit 3.4 release candidates).

To enable the backup and restore operations for static attributes, simply pass the --static-backup command-line switch, use the @backupStaticAttributes annotation, or the XML configuration file.

Below is the full list of changes:

  • Fixed #889: --skeleton-class does not work with @depends annotation. [5270]
  • Fixed #902: PHPUnit_Util_File::getClassesInFile() does not handle nested namespaces correctly. [5272]
  • Fixed #905: Files with no methods or classes show incorrect code coverage with --coverage-clover. [5276] [5284]
  • Fixed #909: Stubbing a web service with getMockFromWsdl() throws a fatal error. [5281]
  • Fixed #918: Truncate operation throws an error. [5286]
  • The backup and restore operations for static attributes has been disabled by default. [5288]

September 25, 2009

Lars Jankowfsky

Upcoming talks…

After my discussion with Arno about the right way to develop software I’ve decided that it would be a good chance to meet him in person while visiting PHP Con in Barcelona. And besides that, Barcelona and the PHP Folks there is always good for a visit.

Therefore there is - once again - another chance to enjoy my talks called ‘Refactor it! A practical journey into the test-driven world’ and ‘Agile Development with PHP in Practice’ . I did run both topics already quite often but obviously there is still a need for it. If you are new to agile development or interested in refactoring your old (shitty?) sourcecode - come in and join.

And if you are interested in the topic of the discussion with Arno - feel free to contact me. I will organize a meeting with where we will discuss the whole item over a few bottles of red wine. After receiving so many comments it would be nice if we get a few more opinions together.

After Barcelona Summer is definitly gone and it’s - as every year - time for the international PHP Conference in Karlsruhe. This time Thorsten and me will run a half-day Workshop called “Unittest for Dummies” which will address unit testing beginners. If you are not already into TDD you should definitly consider to come. Furthermore there will be a session about how swoodoo managed to withstand the massive amount of requests due to (*yeah*…) the big success. I’ve titled it “caching, sharding, distributing - Scaling best practices” - so you might get an idea about the contents.

That’s it - live from the “Oktoberfest” in munich ;)

September 16, 2009

Sebastian Bergmann

PHPUnit 3.4.0

A year and a day has passed since the release of PHPUnit 3.3. Time to finally release PHPUnit 3.4.

Among the features introduced in this new version, the most notable are the support for test dependencies and fixture reuse as well as the possibility to run tests in separate PHP processes for increased test isolation. Please have a look at the ChangeLog for a complete list of changes.

Work on PHPUnit 3.5 has already started: the php-code-coverage project on GitHub is home to a refactoring of PHPUnit's code coverage functionality that will be one of the "hallmark features" of PHPUnit 3.5. It will also make PHPUnit's code coverage functionality available outside the scope of PHPUnit.

August 27, 2009

Lars Jankowfsky

Extension Terror?

When I first saw the posting about ‘bad’ code in OXID over at phpterror I wondered if I could ignore this - but now I’ve realized that this article was published on Planet-PHP and even more - other people start to copy the content of the article.

As I am the guy who introduced the disliked functionality many years ago ( actually years before ZF popped up) I feel the need for a statement to put the things into the right order. Please note that I did work for OXID in the past (years ago) but I do not nowadays.

Arno criticised the way modules == classes are instantiated in OXID eShop. Actually I do believe that exactly this feature is the most coolest in OXID and should be implemented in more OSS.

Let’s start with the “why the fuck did the guy implement this”?

If you do run a website out there you know how important it is to keep it up-to-date with the latest patches due to security reasons. Now imagine - we are in eCommerce area. You deal with payments, credit card data and sensitive information about what people ordered from your shop. Not only Creditcard data is sensitive - imagine it would leak that you ordered the extra-big-boobs doll? You see - especially in this area you need to make absolutly sure that your servers and the software is safe.

Unfortunately you can’t start an eCommerce business out-of-the-box. You need to adopt the software to your needs and processes. Think of payment, ERP, delivery notifications, link to your stock, uploads to price-comparison sites etc. Some of the functionality you might need to develop yourself - for other stuff you might find already existing modules out there.

Therefore you need to change code, and/or install external modules which modify the functionality. In former days you simply edited the source code (as we are talking about OSS) and made manually sure that the modules you install are compatible. Don’t forget - each of them will work with the out-of-the-box shop - but they still should work after you added your changes and - also need to work after you installed some other external modules which might overwrite/change the same classes/functionality which your new module also want to change.

You end up with a highly customized shop, many changes, a lot of work to dig through the sourcecode of the installed modules to make sure that they don’t harm themself and… you lost the possibility to automatically appply patches/releases. Upon each patch or new release you need to manually redo/check your changes.

This sucks. It sucks a lot. And this is exactly why I’ve introduced the criticised module functionality.

So what did I do?

As Arno already copy&pasted the source I won’t repeat it here. But let me explain the main idea behind the concept.

As OXID is fully OOP you can change all the functionality by inheriting your class from any base class you might want to change. You add your changes and - et voila - you still can overwrite the bases classes with new releases/patches and your changes will work. This is called object oriented programming.

Let’s assume you want to change the method “getPrice” in the class “oxarticle”. You simply overwrite oxArticle::getPrice and… it would work if the system would know that your class exists. Therefore you need to register your class and let the OXID Framework know about it so that it automatically will instantiate your class instead of oxArticle each time the object is needed.

So far, so good, so what?

What happens if you install some other module ( e.g. from here) which will change the same method in same class? It would screw your changes and you would end up with manual changes again. To avoid this, the OXID Framework supports “chaining” of inheritance… and the order is set in the config. So you can define that the modules oxArticle implementation is executed before your class or after.

I do believe that by overriding the classes you do get the most flexible option to change everything without loosing the functionality to update the shop whenever you want. For sure this could be solved differently. Events or Hooks would have been a way to go - but this would involve a lot of additional coding == lines of code and therefore introduce new vectors for bugs. And - it is by far not as flexible as overriding the class. Nowadays it could be solved also with Reflection. But this is a bit too “magic” in my opinion. Therefore I still believe that the way I’ve chosen is the best way to solve the problem and - most likely - I would do it again today.

Last but not least - I would like to comment the show me your 94% Unit Test coverage! posting.  I’ve contacted OXID already one year ago about this and I fully agree with Arno here. It sucks to advertise with some test-driven-development features and then keep the tests for yourself. OXID has to change this. Now.

Today I had a good skype discussion about the issue with Arno - I really like his style even though we both do not agree ;) - and the result for me was that  I’ve decided to submit a few proposals to the PHP Conference in Barcelona to get the chance to meet Arno and discuss the whole issue over a bottle of spanish Rioja. Or two. Or…

August 18, 2009

Sebastian Bergmann

PHPUnit 3.4.0RC1

The first release candidate of PHPUnit 3.4 is now available.

Among the many new features introduced in this new version, the most notable are the support for test dependencies and fixture reuse as well as the possibility to run tests in separate PHP processes for increased test isolation. Please have a look at the ChangeLog for a complete list of changes.

You can help make PHPUnit 3.4 a "good release" by running your test suites with it and report any problems or regressions that you may encounter. You help is much appreciated!

July 08, 2009

Stefan Priebsch

PHP 5.3 Release Party

PHP 5.3 BBQ Release Party München Wir würden dich gerne zu der PHP 5.3 Release Party einladen, bei der das PHP 5.3 Release in München gefeiert werden soll. Der Event findet am Freitag, den 17.07.2009 in München statt. Die Release Party bietet auch die Möglichkeit zu einem lockeren Treffen mit anderen “PHP-Begeisterten”. Natürlich bist du auch [...]

Lars Jankowfsky

PHP 5.3 BBQ Release Party Munich

Folks, it’s Paaaaaaaaaaarty Time!

asado

We like to invite you to the PHP 5.3 release party which is an event to
celebrate the 5.3 release, happening Friday, the 17th of July in Munich.
The release party offers a chance to come together with other php
enthusiasts and enjoy that php is alive and kicking. And of course people
in favour of a decent barbecue, together with some beer and other drinks
are invited.

The happening will take place at Waldwirtschaft beer garden, at any weather. We will meet at 19:00 o’clock - open end. The location is famous for its huge beer garden (2500 available seats, a children’s playground) and its typical Bavarian but also international food. On sunny weather you even may enjoy live-music and listen to the sounds of Jazz, Blues, Swing or Dixi.

Catering will be provided and as a special delicacy you may enjoy a suckling pig!

If you like to join the event please register at PHPUG-Munich Wiki and follow it for updates.
Alternatively you may register at Facebook as well and follow this for updates.

For any questions please visit IRC channel: #phprp on irc.uni-erlangen.de.

The PHP 5.3. BBQ release party is sponsored by:

* Microsoft
* Mayflower GmbH
* Swoodoo AG
* Zend Technologies GmbH

Supporters for the PHP 5.3 BBQ release party are:

Sun Microsystems
PHPUG.de

I hope to see you there!

Update: edited sponsor list

July 07, 2009

Manuel Pichler

The value of complexity metrics - Cyclomatic Complexity (1/2)

Software metrics are currently on everyone's lips and a frequently discussed topic. There are many conference talks, blog posts and other presentations that talk about software metrics. But to me it seems as if this subject is a closed book for many developers, so I decided to write this little post about a special category of software metrics, the complexity metrics.

Complexity metrics are a theoretical approach to measure the subjective complexity of a software fragment, where the words software fragment stand for a paraphrase for functions, methods, classes and nearly every logical unit that can be found in a software system. The most prevalent procedure to calculate complexity values is static code analysis, where an application parses the raw source code of a project, counts different statements and expressions and packs up the determined results in simple classification numbers. And with this information you already know the main concepts behind most software metrics, classification numbers and counting. As you can see there is no magic behind the scene, the only thing required is a good background knowledge to interpret those values.

The Cyclomatic Complexity Number or short CCN is the oldest complexity metrics. The first time this software metric was mentioned was 1976 by Thomas J. McCabe. This metric counts the available decision paths in a software fragment to determine its complexity. Each decision path starts with one of the conditional statements from the following list, so that it is fairly easy to detect them in existing source code.

  • ?
  • case
  • elseif
  • for
  • foreach
  • if
  • while

A look at this list of statements may result in the questions: Is this list wrong, it doesn't list else and default? But it is correct. The assumption is that both statements will contain the defaut execution path of a program which also exists when there are no special cases to capture.

Each decision path gets the value 1 and the sum of all these values represents the Cyclomatic Complexity of the analyzed software fragment. Note that each function and method also counts with a value of 1 With this knowlegde we can now calculate the complexity of the following example code:

  1.  
  2. <?php                                 
  3. class CyclomaticComplexityNumber
  4. {
  5.     public function exampe( $x, $y ) // (1)
  6.     {                                               
  7.         if ( $x > 23 || $y < 42 ) // (1)
  8.         {                                 
  9.             for ( $i = $x; $i >= $x &&amp; $i <= $y; ++$i ) // (1)
  10.             {
  11.             }
  12.         }
  13.         else
  14.         {
  15.             switch ( $x + $y )
  16.             {
  17.                 case 1: // (1)
  18.                     break;
  19.                 case 2: // (1)
  20.                     break;
  21.                 default:
  22.                     break;
  23.             }
  24.         }
  25.     }
  26.     file_exists('/tmp/log') or touch('/tmp/log');
  27. }
  28.  

Based on the previous definition the Cyclomatic Complexity Number of the example code example is 5. But you may have noticed that this approach does not capture all decision paths that exist. We haven't catched those paths that came from the by the boolean expression || line 6 and && line 8, and the logical or expression in line 25. A variation of the Cyclomatic Complexity Number that also captures those paths is the so called CCN2. The CCN2 is the most widely used variation of this software metrics. Tools like PHPUnit, PMD and Checkstyle report it as Cyclomatic Complexity of an analyzed software fragment.

Now we get a complexity value of 8 when we apply the CCN2 to the previous example, what is a growt of the software's complexity of 60%.

Due to the fact that Cyclomatic Complexity Number was originally invented for procedural programming languages, this definition for the Cyclomatic Complexity Number still misses one element to measure the complexity of an object oriented software system. With the concept of exceptions a software gets additional decision paths for each catch statement used in the source code. While try contains the code for the regular execution code without special cases, similar to else and default statements.

  • ?
  • &&
  • ||
  • or
  • and
  • xor
  • case
  • catch
  • elseif
  • for
  • foreach
  • if
  • while

Now that we know what the Cyclomatic Complexity Number is, what can we do with the measured information? We can find the complexity hotspots in a system, for example the top ten artifacts with the highest complexity, but this is only important during an initial analyses phase to get the big picture of an application. For a continuous inspection this information is not so important. A continuous analyses requires thresholds that help to categories calculated values. During the time four values have emerged as good thresholds for the Cyclomatic Complexity Number of a software system.

  • A software fragment with a CCN value between 1-4 has low complexity.
  • A complexity value between 5-7 is moderate and still easy to understand.
  • Everything between 6-10 has a high complexity, while everything greater 10 is very complex and hard to understand.

You may ask, why should I care about the complexity of a software system, where is the value of benefit in this metric?

Mostly the complex parts of an application contain business critical logic. But this complexity has negative impacts on the readability and understandability of source code. Those parts will normally become a maintainence and bug fixing nightmare, because no one knows all the constraints, side effects and what's exactly going on in that part of the software. This situation results in the well known saying "Never touch a running system" which in turn mostly ends in copy&paste programming. The situation can even become more critical when the original author leaves the development team or the company.

Finally a small example how to apply the new knowledge about the Cyclomatic Complexity Number, thresholds and the negative impacts of complex software to an existing development process. The following source listing shows a complex method taken from PHP_Depend's source. This method has a Cyclomatic Complexity Number of 16 and I must admit that the original author needed some time to understand what was going on in this method.

  1.  
  2. <?php
  3. // ...
  4. private function _countCalls(AbstractCallable $callable)
  5. {
  6.     $callT  = array(
  7.         TokenizerI::T_STRING,
  8.         TokenizerI::T_VARIABLE
  9.     );
  10.     $chainT = array(
  11.         TokenizerI::T_DOUBLE_COLON,
  12.         TokenizerI::T_OBJECT_OPERATOR,
  13.     );
  14.     $called = array();
  15.  
  16.     $tokens = $callable->getTokens();
  17.     $count  = count($tokens);
  18.     for ($i = 0; $i < $count; ++$i) {
  19.         // break on function body open
  20.         if ($tokens[$i]->type === TokenizerI::T_CURLY_BRACE_OPEN) {
  21.             break;
  22.         }
  23.     }
  24.  
  25.     for (; $i < $count; ++$i) {
  26.         // Skip non parenthesis tokens
  27.         if ($tokens[$i]->type !== TokenizerI::T_PARENTHESIS_OPEN) {
  28.             continue;
  29.         }
  30.         // Skip first token
  31.         if (!isset($tokens[$i - 1]) || !in_array($tokens[$i - 1]->type, $callT)) {
  32.             continue;
  33.         }
  34.         // Count if no other token exists
  35.         if (!isset($tokens[$i - 2]) &&amp; !isset($called[$tokens[$i - 1]->image])) {
  36.             $called[$tokens[$i - 1]->image] = true;
  37.             ++$this->_calls;
  38.             continue;
  39.         } else if (in_array($tokens[$i - 2]->type, $chainT)) {
  40.             $identifier = $tokens[$i - 2]->image . $tokens[$i - 1]->image;
  41.             for ($j = $i - 3; $j >= 0; --$j) {
  42.                 if (!in_array($tokens[$j]->type, $callT)
  43.                     &&amp; !in_array($tokens[$j]->type, $chainT)
  44.                 ) {
  45.                     break;
  46.                 }
  47.                 $identifier = $tokens[$j]->image . $identifier;
  48.             }
  49.  
  50.             if (!isset($called[$identifier])) {
  51.                 $called[$identifier] = true;
  52.                 ++$this->_calls;
  53.             }
  54.         } else if ($tokens[$i - 2]->type !== TokenizerI::T_NEW
  55.             &&amp; !isset($called[$tokens[$i - 1]->image])
  56.         ) {
  57.             $called[$tokens[$i - 1]->image] = true;
  58.             ++$this->_calls;
  59.         }
  60.     }
  61. }
  62.  

The first thing to do is to make sure that the test suite is good enough to ensure that the required refactorings will not change the public behavior of the component or class. When this is donw and we are sure our that api breaks will be detected by the test suitewe can start to extract logic into separate methods.

The following example shows the result of the refactoring:

  1.  
  2. <?php
  3. // ...
  4. private function _countCalls(AbstractCallable $callable)
  5. {
  6.     $called = array();
  7.  
  8.     $tokens = $callable->getTokens();
  9.     $count  = count($tokens);
  10.     for ($i = $this->_findOpenCurlyBrace($tokens); $i < $count; ++$i) {
  11.  
  12.         if ($this->_isCallableOpenParenthesis($tokens, $i) === false) {
  13.             continue;
  14.         }
  15.  
  16.         if ($this->_isMethodInvocation($tokens, $i) === true) {
  17.             $image = $this->_getInvocationChainImage($tokens, $i);
  18.         } else if ($this->_isFunctionInvocation($tokens, $i) === true) {
  19.             $image = $tokens[$i - 1]->image;
  20.         } else {
  21.             $image = null;
  22.         }
  23.  
  24.         if ($image !== null) {
  25.             $called[$image] = $image;
  26.         }
  27.     }
  28.     $this->_calls += count($called);
  29. }
  30.  

The subjective feeling of readability heavily depends on the complexity of control structures, as we can see by a comparison of the original and the refactored version of the method example. The new version with its Cyclomatic Complexity Number of 5 is much easier to read and understand.

This text is the first of two blog posts. The second article will give a short introduction into the NPath Complexity You liked this article and you are interested in this and other quality assurence related topics? - Then you should now order your copy of the Book Quality Assurance in PHP Projects. The book talks about nearly all aspect of quality assurence, with practical tips and expert knowledge contributed by certain PHP professionals.

June 15, 2009

Gabor Szabo

Introduction to PHPUnit

I am returning to the irregular postings of the Test Automation Tips. In this entry you can ready about simple introduction to the PHPUnit testing framework that is used, not surprisingly, to unit test PHP applications.

For the full article visit Introduction to PHPUnit

June 13, 2009

Lars Jankowfsky

Does it ring a bell?

This one reminds me on my past - after seeing it, I feel very happy that I do not do any contracting work any more. I still don’t know if I should laugh or cry. It might be old - but nevertheless worth to watch it.

(English - with German subtitles)

via Guido Muehlwitz

June 06, 2009

Sebastian Bergmann

PHPUnit 3.3.17

  • Fixed #386: Parse error in eval() while mocking SoapClient::__soapCall. [4897]
  • Fixed #782: Missing include in DefaultDatabaseConnection.php. [4876]
  • Fixed #783: Tests getting executed twice when using multiple groups. [4907]
  • Fixed #801: PHPUnit_Util_Fileloader::load() fails silently when file does not exist. [4928] [4929]

June 05, 2009

Quality Assurance in PHP Projects

Unit Testing Bad Practices by Example

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

Although Unit Testing is a recommended practice for any software project, care has to be exercised such that testing yields the desired benefits. Bad programming practices in both test code and production code can make Unit Testing a nightmare. Maintenance of an overly complex test suite can easily become a burden to the project team.

Situations of hard to maintain test code can have extremely negative outcomes for project quality. Programmers start to ignore tests, because of their inconclusive description of what is going wrong. New features might not be tested at all, because writing tests for the current architecture considerably extends development time. In the end the project manager might decide to stop Unit Testing alltogether, because the costs outweight the benefits.

Bad practices of Unit Testing manifest in so called "Test Smells". These are an early indicator of problems for long-run maintainability and utility of a project test suite. To constantly derive a benefit from Unit Tests, a commitment for high quality tests has to be made.

This case study will discuss Unit Testing bad practices and well as Test Smells and gives hints on how to avoid them. For each test smell, examples are shown from well-known PHP Open Source projects. As a result, the reader should be aware of the possible pitfalls of Unit Testing and that any test code requires the same care that is put into production code.

Benjamin Eberlei is a Project Lead with direkt effekt GmbH and contributes to the Zend Framework and other Open Source projects.

May 29, 2009

Quality Assurance in PHP Projects

Testing Service-Oriented APIs

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

One of Zend Framework's key strengths and differentiators in the crowded PHP framework arena is its offering of web service consumer components. As of version 1.8.0, these include offerings for Adobe AMF, Akismet, Amazon (including EC2 and S3 support), AudioScrobbler from last.fm, Del.icio.us, Flickr, Google's GData services, Nirvanix, ReCaptcha, Simpy, SlideShare, StrikeIron, Technorati, Twitter, and Yahoo! -- and more are planned or under development.

Offering components to interact with web services is relatively trivial -- but testing them offers a very different story. For continuous integration purposes, it is typically better not to test against live services as this introduces network latency, and thus slows the testbed. Additionally, many services have API call limits, and automated test suites could easily rise far above these limits. There are also concerns about keeping sensitive API keys or credentials in the repository; some services are paid services, and such information would present a breach of security or contracts.

Over time, the Zend Framework team and contributors have developed a set of practices to address these issues that range from mocking the request and response payloads to offering different tests when credentials are provided via configuration. These practices can lead to well-tested service-oriented components and ensure that the end user experience is as documented.

Matthew Weier O'Phinney works for Zend Technologies Ltd. and is the Project Lead for the Zend Framework.

May 27, 2009

Lars Jankowfsky

IPC09 - Why Architecture in Web Development matters

IPC in Berlin is still in progress and I feel a bit wasted after too much alcohol during the last two days. I think I need a holiday to recover.

For the ones interested - yesterday I had my talk about Architecture in Web Development - and here are the slides. Seems like slideshare ruined the layout when converting - sorry - you have to live with that. The slides probably won’t be of much help if you did not attend the talk. Anyway - here we go:

View more PDF documents from dodgeris.

May 22, 2009

Quality Assurance in PHP Projects

Continuous Integration with phpUnderControl

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

One of the most important events in large and distributed team projects is the integration of all parts of the software system into a release. Often incompatibilities and hard-to-detect errors surface at that very moment and can harm the success of the project. The remedy for this problem is the practice of Continuous Integration: a merge of all parts of the system as often as possible during the lifecycle of the project.

In this case study, we will take a look into the preconditions to start with Continuous Integration as well as the procedural and technical rationales of this approach. We will take a look at entering Continuous Integration in PHP projects with phpUnderControl, a customization of the popular and established Continuous Integration server software CruiseControl.

Beyond Continuous Integration, this case study introduces the reader to the principles of Static Testing and how to instrument it to gain a better quality. Amongst other tools, the reader will learn how to successfully use tools such as PHP_CodeSniffer, PHP_Depend and phpcpd for Static Code Analysis.

In conclusion, advanced usage scenarios of the discussed tools will be discusses with a particular focus on how to foster further principles of Agile Software Development methodologies and how to solve discrepancies with other targets of agile methodologies.

Manuel Pichler is the creator of phpUnderControl, PHP_Depend, and phpmd. Sebastian Nohn is the Team Lead Quality Assurance at Ligatus GmbH.

May 20, 2009

Sebastian Bergmann

May 17, 2009

Lars Jankowfsky

Speaking the Speaker….

Recently I had the chance to visit two SEO Conferences (smx and semseo) here in Germany. Phew - I can tell you these people know how to party. Not that I do not enjoy the evenings at the php conferences I usually attend, but hey - when was the last time at a php conference where there was an organized coyote ugly party and the crowd was filled up with tequila from nearly naked beautiful women? At least I can’t remember. Followed by that I’ve enjoyed a karaoke show where one of the organizers - Alan Webb from Abakus presented his version of Sinatra’s - or was it Sid Vicious? - version of ‘My Way’. Well - we definitly can learn from the SEO folks a lot about partying. Maybe we will enjoy Bjoern Schotte singing and dancing in Berlin? Would love to see this.

Back to business - let’s get a bit more serious.

For me it was a quite unusual experience being a visitor and not one of the speakers so I could experience how difficult it is as a ‘plain’ visitor to get into touch with the speakers. In every ’scene’ the speakers usually know each other for a quite long time and enjoy to meet again - so it is for me on the PHP Conferences. We gather, hang around, talk, drink and have fun. Nothing wrong with that. Only - if you are not a ‘member’ of the speaker crowd it might feel a bit difficult to enter the conversation and get into touch with us. Especially developers tend to be bit shy - not much of us you could call ‘extrovert’. Humm… well besides me.

PHP is open source, driven by the community. And this is about you. Some of the speakers on the conferences around the world might contribute a bit more than you do - but nevertheless you are part of the community. So you are part of the ‘crowd’ and so you should act.

So if you want to get into touch with me for any reason then feel free to approach me any time. I will happily answer your questions, share a beer with you or will help you to get into contact with other people you are interested in.

Next chance to meet me is on the IPC Spring Edition in Berlin next week. Hope to see you there!

May 08, 2009

Quality Assurance in PHP Projects

Testing Symfony and Symfony Applications

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

In this case study, we will talk about how the Symfony framework itself is tested, but also about the tools the framework provides to ease testing the customer applications.

Although developers are well educated now about tests, it is still the most neglected part of a web development process. Most developers still think they cannot afford writing tests because it takes too much time. The Symfony framework tries to ease the creation of both unit tests and functional tests with a unique and simple approach. For instance, functional tests are done by simulating a browser experience, but with the possibility to introspect all internal objects between each request. It is also possible to validate the generated content easily and precisely thanks to CSS3 selectors.

Testing the framework itself also proved to be quite challenging, and we learned it the hard way: from code that is too coupled to be tested thoroughly, to the usage of design patterns like the Singleton. Over the years, the Symfony framework quickly evolved from our testing experience, and now provides a well decoupled, but cohesive set of components. For Symfony 2, the introduction of a Dependency Injection container will be of great help to ease the testing process even more.

Fabien Potencier is the CEO of Sensio and the lead developer of Symfony.

May 06, 2009

Mike Naberezny

Faster TDD with Stakeout.rb

I’m a big fan of Autotest and it runs almost constantly on my machine. Autotest automatically reruns your tests whenever your files change. Instead of constantly flipping to another shell to rerun your tests, just let Autotest cheerfully do it for you in the background. It’s highly addictive.

The only problem with Autotest is that it is specific to Ruby. At work, I do a mix of different kinds of programming including Ruby, PHP, Python, and C. I’d like my TDD to be accelerated for all of these languages.

Thanks to Geoffrey Grossenbach, last week I came across stakeout.rb from Mike Clark. This is a tiny, dead simple Ruby script that runs an arbitrary command when certain files change. This is a stripped-down Autotest for everybody else. I’m sure it has all kinds of other uses as well.

To get started testing with stakeout.rb, you’ll need Ruby installed. Any recent version is fine and you might already have it installed. Next, grab the stakeout.rb script and add the shebang line to the top (Unix-like OS assumed):

#!/usr/bin/env ruby -w
 
if ARGV.size < 2
  puts "Usage: stakeout.rb <command> [files to watch]+"
...

Make the file executable and put it somewhere in your PATH. You can test it out by typing stakeout.rb from an arbitrary directory and you should see the help message.

Next, change over to a project directory where you have some test files. Most of the projects that I am involved with tend to use some directory structure similar to this:

/project_name
  /lib
  /test
  ...

To test such a project, run stakeout.rb from the /project_name directory. Most PHP projects using PHPUnit tend to have an AllTests.php file or equivalent to run all the tests, so we’ll assume this for the example:

project_name$ stakeout.rb "php test/AllTests.php" **/*

The first argument is what command to run when the tests change. The second argument, and any subsequent arguments, are the files to watch for changes. These can use a Ruby globbing pattern. The pattern **/* will watch all files under project_name recursively, which includes lib/ and test/.

Once stakeout.rb is run, it will show no output but will sit and wait for changes. As soon as you change a watched file, stakeout.rb will automatically rerun you tests and will continue to do so until you exit with Control-C.

May 01, 2009

Quality Assurance in PHP Projects

TYPO3: The Agile Future of a Ponderous Project

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

When Kasper Skårhøj wrote the first lines of PHP code laying the foundation for the TYPO3 CMS in 1998, he had not the slightest idea that a big part of the code he wrote would still be actively used ten years later. Adding the 3700 extensions contributed by an ever growing developer community resulted in an impressive amount of code - of varying quality.

Without surprise it soon became a challenge to assure a high quality and secure product. While the core developers were eager to add new features, the holy cow of backward compatibility was lurking at the next corner, waiting to be fed. The result is a feature-rich and solid but equally monolithic and complex pile of code that is, at best, hard to test. As a consequence we decided to rewrite TYPO3 from scratch.

In this case study we will share our experience with the technical and organisational techniques we have chosen for the development of TYPO3 version 5 and its foundation, the FLOW3 framework. It explains our pedantic pursuit of clean code, outlines our commit and coding guidelines and gives answers to tricky situations you face while writing and maintaining (true) unit tests. Finally we demonstrate how a clean architecture can help you tackling the complexity of your application.

Robert Lemke and Karsten Dambekalns are core developers of both TYPO3 and FLOW3.

A few recipes for writing good unit tests that are part of this case study are demonstrated in the "Delicious Test Recipes" episode of Robert Lemke's podcast.

April 17, 2009

Quality Assurance in PHP Projects

Testing the ezcGraph Component

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

The Graph component from the eZ Components project provides an easy to use and extensible library for creating graphical charts. In the eZ Components project we aim to develop test-driven, which resulted in two challenges developing this library.

The output generated by a Graph component is an image, which in most cases is binary-encoded data. Expectations are really hard to create by hand, it is only feasible to create functional tests replaying once created data. The actual image is generated by external libraries such as ext/gd. These external libraries may change their exact output at any time, or even between two runs with the same version of the library. Comparisons of the generated images need to respect that and implement special assertions for the given type of binary data.

Testing the created binary data has proven to be prone to errors. Since the actual image generation has been abstracted away, we are able to use of different image creation mechanisms. Thanks to the support for mock objects in PHPUnit, all calls to the driver layer can be checked for correctness without actually generating images.

Kore Nordmann is an active member of the PHP community and works for eZ Systems on the eZ Components.

April 10, 2009

Sebastian Bergmann

PHPUnit 3.3.16

  • Fixed #712: Custom TestCase base classes are not handled properly. [4790]
  • Fixed #728: Loading Selenium test suite from config file does not work. [4686]
  • Fixed #736: Regression in test autoloading. [4787]
  • Fixed #737: Diff operation fails when /tmp is not writable. [4748]
  • Fixed #758: Wrong double quotes on Oracle statements. [4784]
  • Fixed #759: DBUnit loads constraint definitions of others schemas. [4784]

Quality Assurance in PHP Projects

Quality Assurance at Digg Inc.

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

Digg's development philosophy has changed dramatically in the last year in an attempt to move towards a more agile and iterative approach. A large part of these sweeping changes is moving toward a test-driven development methodology with a minimum of 80% code coverage.

Integrating unit testing into coding practices is a daunting task at first glance. It requires adjusting how developers work in almost every respect, but it can also greatly assist in debugging and validating your code. We wanted to get this right the first time, so we decided to hire an outside contractor to help us formulate a plan of attack. Once we decided upon a course of action, it took only a week for the contractor and two developers to build a test harness and small suite of tests for our core classes, we even found a handful of bugs along the way. Next, we worked to instruct the remaining developers at Digg of best practices for writing unit tests.

Although in one week we went from having only a handful of previously written tests to having a framework to build unit tests much more easily, our work was far from complete. Even our QA team has dramatically changed how they operate to take advantage of the benefits unit testing offers.

Our case study will discuss in depth benefits and drawbacks of adopting test-driven development, cover the gamut of unit testing from simple assertions to mocking complex objects, and dissect the continuing challenges we face.

Robert Balousek, Matt Erkkila, Ian Eure, Bill Shupp, Jeremy McCarthy and Brian O'Neill all contributed to the case study and are employees of Digg.

April 03, 2009

Quality Assurance in PHP Projects

Large-Scale Selenium-Based Testing

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

A well established practice in web application development is testing a web-based GUI as a whole in order to ensure its functionality.

At studiVZ, we have to test three different platforms in two languages. There are many platform-specific differences, in both wording and functionality. The scenario is even further complicated by the use of AJAX functionality in some features. With a release cycle of 14 days, this is indeed a challenge for a small quality assurance team.

In addition to Unit Tests, Acceptance Tests are the main part of our automated testing strategy. There are thousands of acceptance tests that have been written since the rewrite of the platform in early 2008. Because of our special requirements (tests have to work for three platforms) we decided not to use one of these capture-and-replay web testing softwares but to write our tests by hand. We chose Selenium RC and the Selenium RC extension for PHPUnit that allows to write and execute acceptance tests in a unit test style.

But writing acceptance tests is a rocky road to success. The main problem with acceptance tests is their fragility: they will break when the code changes. Another challenge is keeping the tests maintainable, foremost readable. This was the motivation to create a domain-specific language for PHP that allows us to write tests in the language of our business rather than in Selenium's language.

We want to share our insight into the specific challenges of acceptance testing and how to handle them. Furthermore we will talk about our experiences and learning curve with a DSL-based framework for Selenium tests.

Christiane Philipps is the Team Lead Quality Assurance and Max Horváth is the Team Lead Mobile Development at studiVZ Ltd.

March 27, 2009

Quality Assurance in PHP Projects

Testing Database Interaction

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

Proper interaction with relational databases is incredibly important in most pieces of software. The importance of this interaction is underscored by the fact that many software architectures have at least one entire layer or system devoted to data persistence and data loading. When dealing with critical data in enterprise level applications it becomes even more important to make sure your data is being stored and retrieved correctly.

As responsible developers, one of our goals should be to test database interaction and test it well. To help achieve this goal, we will take a close look at tools and techniques that can be used with projects of any size to help create reliable tests capable of validating your database interaction.

The discussion will begin with various techniques for testing your database layer. The focus will then move toward the functionality in the database extension for PHPUnit. Then, utilizing the tools provided in the database extension, examples will be given of how to create basic tests validating that the database is correctly manipulated and data from your database is successfully retrieved. This will be followed by an in depth discussion of "best practices" that can be utilized when you are developing "database aware" fixtures and tests.

Once the ground work is laid, we will look at how all of these tools and techniques can be utilized in both your unit tests and functional tests.

Michael Lively Jr. is the Lead PHP Developer for Selling Source, LLC.

March 21, 2009

Lars Jankowfsky

Bye Bye bella Roma

The last few days I had the pleasure to visit the PHP Conference in Rome. It was - as usual - really good organized and even though it was not that big as other conferences I personally think that it was quite successful. And for sure the location… thousands of years of culture. There is simply no other city in the world with the age and the cultural background like Rome.

As promised here are my presentations:

View more presentations from dodgeris.
View more presentations from dodgeris.

( V2 as this is an improved version now with better examples using OXID eShop to show the power of selfmade Nagios/Cacti plugins)

March 20, 2009

Quality Assurance in PHP Projects

Testing a WebDAV Server

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

The eZ Components project was started with the goal to create a high-quality set of independent building blocks for PHP 5 based application development. Making extensive use of unit tests and sticking to strict development and documentation standards were defined as the basic methodology. One of the biggest challenges in terms of testing and quality assurance so far was the eZ Webdav component.

The eZ Webdav component is intended to provide a modular WebDAV server to be embedded in any kind of web application. Its architecture is built to be as customizable and extensible as possible, while it tries on the other hand to compensate the weaknesses of the RFC and common WebDAV clients.

Testing a server is a challenge in general. Testing the WebDAV component brought us to the limit of unit testing and forced us to find new ways of using PHPUnit to ensure code quality and to obviate regressions. Unavoidable deep code dependencies in some parts of the server enforced the extensive use of mock objects to stick to the unit test paradigm. In some areas, like avoiding regressions in the adjusted behavior against special clients, unit testing was even impossible. For this reason, special record/playback-based tests were created and implemented using PHPUnit.

Tobias Schlitt is an active member of the PHP community and works for eZ Systems on the eZ Components.

March 18, 2009

Sebastian Bergmann

March 15, 2009

Sebastian Bergmann

Quality Assurance Tools for PHP

Map of PHP QA Tools

The map above contains the following tools that are useful for quality assurance in PHP projects:

  • PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.
  • phpmd scans PHP source code and looks for potential problems such as possible bugs, suboptimal code or overcomplicated expressions.
  • phpcpd is a Copy/Paste Detector (CPD) for PHP code.
  • PHP_Depend is a PHP software metrics tool.
  • PHPUnit is the de-facto standard unit test framework for PHP.

Build Automation is the act of scripting or automating a wide variety of tasks that a software developer will do in their day-to-day activities, including tasks that involve the tools listed above.

Apache Ant is a Java-based build tool that is similar to make, but without make's wrinkles. Its build files are XML-based, calling out a target tree where various tasks get executed.

The listing below shows an Apache Ant build file for a project named Money.

<project name="Money" default="build">
 <target name="clean">
  <delete dir="${basedir}/build"/>
 </target>

 <target name="prepare">
  <mkdir dir="${basedir}/build/logs"/>
 </target>

 <target name="phpcs">
  <exec dir="${basedir}"
        executable="phpcs"
        output="${basedir}/build/logs/checkstyle.xml"
        failonerror="false">
   <arg line="--report=checkstyle ."/>
  </exec>
 </target>

 <target name="phpmd">
  <exec dir="${basedir}"
        executable="phpmd"
        failonerror="false">
   <arg line=". xml codesize
              --reportfile ${basedir}/build/logs/pmd.xml"/>
  </exec>
 </target>

 <target name="phpcpd">
  <exec dir="${basedir}"
        executable="phpcpd"
        failonerror="false">
   <arg line="--log-pmd=${basedir}/build/logs/pmd-cpd.xml ."/>
  </exec>
 </target>

 <target name="pdepend">
  <exec dir="${basedir}"
        executable="pdepend"
        failonerror="false">
   <arg line="--jdepend-xml=${basedir}/build/logs/jdepend.xml ."/>
  </exec>
 </target>

 <target name="phpunit">
  <exec dir="${basedir}"
        executable="phpunit"
        failonerror="true">
   <arg line="--log-xml         ${basedir}/build/logs/junit.xml
              --coverage-clover ${basedir}/build/logs/clover.xml
              MoneyTest"/>
  </exec>
 </target>

 <target name="build"
         depends="clean,prepare,phpcs,phpmd,phpcpd,pdepend,phpunit"/>
</project>

The main target, build, depends on the targets that

  1. Delete the build directory, if it exists.
  2. Prepare the build directory, if it does not exist.
  3. Run PHP_CodeSniffer on the project's sourcecode and write a logfile in Checkstyle XML format.
  4. Run phpmd on the project's sourcecode and write a logfile in PMD XML format.
  5. Run phpcpd on the project's sourcecode and write a logfile in PMD-CPD XML format.
  6. Run PHP_Depend on the project's sourcecode and write a logfile in JDepend XML format.
  7. Run the project's tests using PHPUnit and write logfiles in JUnit XML and Clover XML format.

Below is the output for invoking Apache Ant in the project directory:

sb@ubuntu Money % ant
Buildfile: build.xml

clean:
   [delete] Deleting directory /home/sb/Money/build

prepare:
    [mkdir] Created dir: /home/sb/Money/build/logs

phpcs:

phpmd:

phpcpd:
     [exec] phpcpd 1.1.0 by Sebastian Bergmann.
     [exec] 
     [exec] 0.00% duplicated lines out of 722 total lines of code.

pdepend:
     [exec] PHP_Depend 0.9.4 by Manuel Pichler
     [exec] 
     [exec] Executing Dependency-Analyzer:
     [exec]                                                                 16
     [exec] 
     [exec] Generating pdepend log files, this may take a moment.

phpunit:
     [exec] PHPUnit 3.4.0 by Sebastian Bergmann.
     [exec] 
     [exec] ......................
     [exec] 
     [exec] Time: 0 seconds
     [exec] 
     [exec] OK (22 tests, 34 assertions)
     [exec] 
     [exec] Writing code coverage data to XML file, this may take a moment.

build:

BUILD SUCCESSFUL
Total time: 4 seconds

The generated logfiles can be processed by CruiseControl because it already knows the XML formats used. phpUnderControl is a customization of CruiseControl that caters to the needs of PHP projects and makes a lot of things easier.

Sonar enables to collect, analyze and report metrics on source code. It not only offers consolidated reporting on and across projects throughout time, but it becomes the central place to manage code quality. The developers of Sonar are working on out-of-the-box support for PHP projects.

March 13, 2009

Quality Assurance in PHP Projects

swoodoo - A True Agile Story

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

swoodoo, the Germany-based flight search engine, has gone through a wild evolution. In 2003 it started out as a peer-to-peer network with ActiveX browser plugins written in C++ to query cheap flights. It went through a Java-centric solution using various techniques for screenscraping data from airline websites and finally has evolved into a robust architecture where Java and MySQL are used in the backend and PHP plays a major role in all frontend-related tasks as well as in data gathering from airlines.

Besides technology, the software architecture has also changed immensely: from distributed objects to a "big ball of mud" and finally into a Service-Oriented Architecture (SOA) with clearly defined interfaces between separate services. In order to have a better control of swoodoo evolution, project management was switched to Extreme Programming (XP) in the beginning of 2007. At the same time we introduced unit testing using JUnit and PHPUnit as well as PHP-driven Selenium acceptance testing. Initially we made heavy use of Selenium but recently we have reduced the amount of Selenium tests - a tradeoff we had to make because of the nature of our SOA-based architecture.

In this case study we want to show the evolution of our agile management techniques, testing environment, tools and approaches we use and why we decided to change in case we did.

Lars Jankowfsky is the CTO of Germany-based swoodoo AG.

March 06, 2009

Quality Assurance in PHP Projects

Performance Testing

This is an abstract for a chapter from a book on Quality Assurance in PHP Projects.

Incorrect application functionality is a detriment to any project, but poor performance and scalability can often lead to end-user dissatisfaction and exorbitant hardware expenses.

In the case of modern web application, expectations have made it necessary to provide responses within as little as 100 to 500 milliseconds. This puts a tremendous burden on not only achieving excellent performance, but maintaining consistent performance as code changes and new features are added.

We will review a variety of tools that can be used to test performance and scalability. While the stack will be assumed to be Linux, Apache, MySQL and PHP (LAMP), the basic skills and tools can be applied to a variety of systems (and often the ability to correctly test different system components is itself a valid test case).

An initial emphasis will be on the most basic end-to-end testing of the entire request and response cycle, but later will detail smaller benchmarks and developing custom tool sets once you require more precision. Operating System metrics are also key to ensuring an application's scalability and performance, so tools such as sar, strace, and oprofile will be covered. Because performance testing has unique requirements and challenges we will cover methodologies to correctly implement performance tests, benchmarks and the pitfalls to avoid. These include the short term assurance of accuracy, reproducing results, as well as long term goals and how to balance future expectations, growth, and priorities of an entire product or service.

Brian Shire is Facebook's technical lead for PHP internals and a developer for the Alternative PHP Cache (APC).

March 05, 2009

Quality Assurance in PHP Projects

Introduction

Stefan Priebsch and myself, Sebastian Bergmann, are writing a book on "Quality Assurance in PHP Projects". The book will be published in English and German at the same time later this year.

The idea for the book is that Stefan Priebsch and I write the introductory as well as the concluding chapters while other authors contribute case studies for the middle part of the book.

The case study authors will not always agree with each other. In fact, we invite different opinions on how problems are solved to give the readers not "one single truth" but provide different approaches to problems and views on issues.

Our motivation to write this book is simple: there is no such book on the market and from our experience a book such as this is needed. We get questions from our clients all the time: which book can I get for my developers or recommend to potential job applicants as required reading for the topic of web application quality assurance? This book will be the answer to these questions.

The list of case study authors includes contributors to well-known Open Source projects from the PHP community as well as developers working on some of the largest websites built using PHP, which happen to be some of the Web's most popular sites. Other contributing authors write about practices and tools.

Over the course of the next weeks, we will introduce each case study author together with the case study he or she is contributing to the book.

March 03, 2009

Lars Jankowfsky

Book your holiday in the concentration camp?

Interesting title isn’t it ? Sounds macabre? It is!

During my work at swoodoo.com (german only, sorry) I accidentially stumbled upon translation issues concerning the city “Kaunas” (Lithuania) on other - travel related - webpages.

The city Kaunas was translated into “KZ Kauen“.

Actually “KZ” means “Konzentrationslager” == Concentration Camp. And “Kauen” is the old “Nazi” name for Kaunas. In Kaunas was the largest concentration camp in Lithuania where the Nazis killed around 25.000 people.

Interested in a hotel in the concentration camp?

kayak-detail

More over - and this is the reason why I post this under the “PHP” flag - I want to show how dangerous it is to copy translations from other websites. Exactly this seemed to have happend - there is a bunch of websites out there who obviously copied from the same source.

Want a cheap flight into the concentration camp?

dohop-google

Or interested how the weather is in the concentration camp ?

wettercom

And even worse - Adwords booked on the term “KZ Kauen”

adword

I doubt that they booked this adword, most likely it is “Dynamic Keyword Insertion”… but nevertheless quite macabre.

If you are into I18n then you should take translation serious. Quite often translated webpages simply sound silly or funny, but as you can see in this example - sometimes it can be worse.

February 25, 2009

Manuel Pichler

phpUnderControl tutorial

Just now I found in Felix's blog this excellent phpUnderControl tutorial that comes with useful tips and helping scripts. Because I think it is a really good source to get started with phpUnderControl I will link it here.

Sebastian Bergmann

Fixture Reuse in PHPUnit 3.4

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.

February 06, 2009

Sebastian Bergmann

PHPUnit 3.3.14

  • Fixed #692: PHPUnit works related on order of --bootstrap and --skeleton-test switches. [4581]
  • Fixed #697: PHPUnit incorrectly instantiates SeleniumTestCase tests with multiple browsers. [4608]
  • Fixed #702: Incorrect text in PHPUnit_Framework_ComparisonFailure_Array. [4613]

February 01, 2009

Mike Lively

YAML Now Supported by PHPUnit Database Extension

I have now just committed YAML data sets to the Database Extension for PHPUnit. So now all those that love the simplicity and straightforwardness of YAML can use it with your data sets. I have also created a persistor for YAML datasets so you can easily convert existing data sets or database data into YAML representations.

This is really the first I have dealt with YAML and it is definitely a viable alternative for data sets. Here is what they will look like.


table1:
  -
    table1_id: 1
    columnName1: "tgfahgasdf"
    columnName2: 200
    columnName3: 34.64
    columnName4: yghkf;a  hahfg8ja h;
table2:
  -
    table2_id: 1
    column5: fhah
    column6: 456
    column7: 46.5
    column8: "fsdb, ghfdas"
  -
    table2_id: 3
    column5: ajsdlkfguitah
    column6: 654
    column7: blah
    column8: |-
      thesethasdl
      asdflkjsadf asdfsadfhl "adsf, halsdf" sadfhlasdf

The biggest issue I had was figuring out how YAML dealt with trailing line breaks. It appears that '|-' did the trick. It will strip the final line break. Another thing to take note is that indention is important. It doesn't HAVE to be spaces (it can be tabs) it just needs to be consistent. The last thing is that strings do not need to be quoted, but if they are you can use escape characters (like \n.)

This was committed to the trunk of PHPUnit and I anticipate Sebastian will be merging it back into 3.4 shortly.

Improved PHPUnit Filters

I have finally gotten some time to do some long awaited work on PHPUnit. The first on my agenda was a small improvement to filtering. This was related to ticket #526. Essentially I added the ability to do both white list and black list filtering.

For instance, if you wanted to specify an include filter you can do the following:


<?php
//...

$filteredDataSet = new PHPUnit_Extensions_Database_DataSet_DataSetFilter($dataSet);

$filteredDataSet->addIncludeTables(array('table1', 'table3'));
$filteredDataSet->setIncludeColumnsForTable('table1', array('column1', 'column2', 'column3', 'column4'));
$filteredDataSet->setIncludeColumnsForTable('table3', array('column9', 'column10', 'column11', 'column12'));

//...
?>
 

I have also deprecated passing the filter to the constructor. The reason for this is that I would like to begin adding a few more features to the filter and the current method of passing the parameters on the constructor would be unintuitive for these planned features. Basically I think it was a mistake for me to allow the passing of filter data on the constructor to begin with. I anticipate the current method working up to PHPUnit 4.0 but it will not be expanded on and will be removed either in PHPUnit 4 or in a release soon after that.

So, for exclude filters, instead of specifying them in the constructor, the new method will be:


<?php
//...

$filteredDataSet = new PHPUnit_Extensions_Database_DataSet_DataSetFilter($dataSet);

$filteredDataSet->addExcludeTables(array('table2'));
$filteredDataSet->setExcludeColumnsForTable('table1', array('table1_id'));
$filteredDataSet->setExcludeColumnsForTable('table3', array('table3_id'));

//...
?>
 

While you can't mix include and exclude filters for tables (wouldn't make sense right now) you CAN do this for table columns of separate tables:


<?php
//...

$filteredDataSet = new PHPUnit_Extensions_Database_DataSet_DataSetFilter($dataSet);

$filteredDataSet->addIncludeTables(array('table1', 'table3'));
$filteredDataSet->setExcludeColumnsForTable('table1', array('table1_id'));
$filteredDataSet->setIncludeColumnsForTable('table3', array('column9', 'column10', 'column11', 'column12'));

//...
?>
 

Some future features I plan on adding include, global column includes/excludes and wild cards. Anyhow, hope this is useful for someone.

January 25, 2009

Sebastian Bergmann

PHPUnit 3.3.11

  • 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]

January 18, 2009

Sebastian Bergmann

The Cost of Test Isolation - Follow-Up

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.

January 13, 2009

Sebastian Bergmann

PHPUnit 3.3.10

  • 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]

Lars Jankowfsky

Upcoming Talks

This year will be very interesting as I will present two talks in Rome, Italy at the PHP Conference. As this will be my first time in Rome I am really looking forward to visit this fabulous place.

My Talks will be:

Monitor your Business

The most important thing happening in your website is the business process. So why should you monitor your database and your webserver only when your business is failing? Monitoring is not only about hardware and databases - it’s also about the internals of your application. Learn how to monitor your business using PHP and how to create nice, good looking management compatible graphs.

This talk will be a highly improved version of the talk I have held at the IPC 2008.

And something new, and (I hope) quite interesting:

Why Architecture in Web Development matters

Choosing the right software architecture for your project is very important. Besides the framework decision there are many other key issues you need to take into account and which have an impact on such things like maintainability, scalability and also the frequency of possible deployments. In this session you will to learn why you have to remove Co-dependency in your source code, which patterns there are for successful scaling and how the choosen framework influences your architecture.

Hope to see you in italy ;)

January 11, 2009

Lars Jankowfsky

Outsourcing and Quality…

Yesterday night I’ve received an interesting comment on my PHP@INDIA posting. After reading I’ve decided that this deserves a posting to answer it thoroughly.

The comment was

The poster who made this statement doesn’t explain to you that India-based workers can only speak about 60% english.

he doesn’t explain that these same developers use BEGINNER LEVEL coding techniques that render your site open to almost the most grade-school level of attacks.

he doesn’t explain to you that these same developers don’t give a damn about you, or your project.

he doesn’t explain to you that their answers to questions are from monitors on their screen, and should you have an advanced-level technical question they are NOT going to be able to answer for you.

And he also didn’t explain that you GET what you PAY for. You pay for garbage in India, expect garbage as a product. You pay good in America for a product, expect the best as a product.

The commentor is right in his statements. Actually talking about Quality in outsourcing you need to take care that the quality is good enough for you. It would be simply very dumb to rely on any developer - check it personally! I’ve made the same experience 10 years ago like my anonymous commentor, but I had to understand that things changed and that it is possible now to get better quality. But as always - you need the right partner.

After reading my posting again I’ve realized that I need to clearify a few things. Outsourcing (in PHP area!) is never about saving money. Having good people inhouse or around the corner will help your project a lot. Outsourcing is about scaling. If you do have any tasks which need to be scaled, like developing the same stuff again and again, editing pictures, running any process against something which need to be repeateded over and over then you should think about offshoring.

I state that it’s very difficult to scale your team from 5 to 15 inhouse fast - and this is possible in india. Simply because there are many indians.

A few rules need to be applied to choose the right partner:

- Do never ever give your core technology to any outsourcer somewhere on this planet. You need to have full control over your technology. Otherwise the risk of beeing ripped off is very high.

- Choose your partner thorougly. Check the references and call them to doublecheck.

- Be aware of your expectations. You will need a few months before the project will run by itself.

- if you do not put in energy, knowhow and your personal sweat it won’t work.

Follow these rules and your outsourcing project will be successful.

To come to an end - yes, also in india you get what you pay for. This is valid anywhere on the planet. Pay your developers well and you will get good quality. And for sure you can not judge over all people in a country - there are good and bad developers all over the planet. Even though it is hard to believe - just beeing american doesn’t make you a good developer - and vice versa - beeing indian doesn’t make you a bad developer.

January 08, 2009

Lars Jankowfsky

PHP@INDIA ?

Did you ever wonder if these Millions of Indian developer we often read about are capabale of doing good in PHP? I did. And I tried.

Back in my past (*cough* - hitting 40 soon…) I’ve outsourced parts of my jobs to many countries, starting with a company in Prague/Czech Republic together with my friend Matthew, and moving later on to lithuania where I still run (together with my mate wolfgang) a development office with a total of 60 developers, coding for various projects like swoodoo or oxid.
During these nearly 25 years I did work for sure in a few projects where coding was outsourced to india. My experience in the past was not really good. The classical project in india was:

- huge
- really huge
- f.. huge

did I mention huge?

Why is that so? Well - the average indian developer is (was!) teached to work as some sort of coding-ant. Don’t think, just do what you gotta do (futurama). Thus this ended in a culture where you need to write a very detailed spec ( thousands of pages) and hand this over to your “ant” farm where 500-1000 developers code what you told them todo. Still you need to check personally the quality as (in the past!) the indian culture does not support being honest in case of problems as this is considered rude. Ah - being rude… tell me.. the ones out there who had the pleasure… to meet me in person know that I am a really honest person thus it is very easy that myself is been taken as rude….

So this was the past - 12 years ago. In 2008 I’ve started a second try - and guess what ? It worked! After investigating the right partner via my personal network I’ve started to work with Anantara. A small company, with very bright minds in management, reliable and trustworthy. Nothing what you can expect anywhere on the planet.

Anantara was working in the usual areas - Java and .NET but not very much in PHP. So I helped them a bit to kickstart a fresh PHP team - and they kept their promises and delivered a good working team. To my pleasure they realized that the PHP area is a very interesting market to them, so they decided to put a lot of energy in this area - sic! Times are really changing, especially now when we talk about the crisis - it matters what you pay for your software, and PHP is simply a lot of cheaper (aka faster) developed compared to .NET and java.

Don’t get me wrong - outsourcing is always difficult and by far less efficient compared to in-house developers. You always have to bridge a cultural/business gap which is most likely there. You can’t expect that some people anywhere on the planet earth understand your business needs without teaching them thoroughly.

But - in the past I had much worse experiences - and now I’ve really enjoyed to work with Anantara the last year. Our project stopped now, as it ended succesfully, but I am definitly looking forward to work with these guys in future again. From a PHP skill level I would estimate that there is average know how - which is better than many code I’ve seen in the last years developed in germany. Needless to say that they do agile development - what else…;)

So - if you are interested in contacting them or you do have any other question concerning outsourcing - feel free to contact me. I’ve decided to support Anantara a bit as I really do like them - and no - I am not paid, nor am I a shareholder there. Most likely they will pay me a beer (or two…) :)

January 06, 2009

Lars Jankowfsky

7 things….

Already a few days ago I got tagged by Manuel Pichler and Gaylord Aulke. I could not post as I was really sick the last two weeks. Today is the first day where I see light at the end of the tunnel and I feel good enough to answer the questions.

So you really want to know seven things about me ? Well - you asked for it :)

1. I earned my first money by creating a blackmarket in secondary school for sexual explicit material, which I bought cheap and sold expensive. This was one of the reasons I had to leave this school.

2. My first love was named Commodore 64. I teached myself Assembler and started to rip off music from games, creating my own demos.

3. My holidays are usually spent in croatia as my beloved wife was born there.

4. I work with a bunch of developers in lithuania, and hey - these guys (and girls!) are really good.

5. Recently I donated my book collection of > 2500 science fiction and fantasy books to a shop where handicapped sell the books to life from that.

6. Although I was born in bavaria my limit are 3 litres of beer, after that I am really really drunk.

7. I can’t stand cold weather - I feel well at an average of 26+ degrees. Oh, do you remember 4. ? In .lt the winters are really really REALLY cold and I hate it.

So - now my turn. Not so easy. I think nearly everybody who I know was already tagged, therefore - sorry about that - I need to tag a bunch of german people who I think are not yet tagged by this meme.

Here we go:

1. Nils Langner for teaching PHP ;)
2. Thorsten Rinne just to remember him that he still ows me a self cooked thai menu.
3. Xenjo because I am curious what he would write….
4. Ralf Eggert to support his upcoming Zend Framework book (in german only)
5. Christopher Kunz who runs partly my servers for swoodoo and takes care about themeven from holiday. Thanks Chris !
6. Tomas Liubinas one of the .lt developers I mentioned and actually he was part of the team who won in plat-forms contest.
7. Max Horvath for… hmm… I still wait for the pics ;)

These are the rules apparently:

Link your original tagger(s), and list these rules on your blog.
Share seven facts about yourself in the post - some random, some weird.
Tag seven people at the end of your post by leaving their names and the links to their blogs.
Let them know they’ve been tagged by leaving a comment on their blogs and/or Twitter.

January 02, 2009

Sebastian Bergmann

Using Bazaar for PHPUnit Development

Last December, when I was in Australia and started to work on the Object_Freezer code, I "dived into" Bazaar (bzr) and learned the value of local commits as they allow me to work offline, e.g. when disconnected during travel.

Thanks to bzr-svn, I can now work offline for PHPUnit development as well.

Here is my setup:

Firstly, setup a local shared repository for storing your branches in and checkout the trunk:

sb@ubuntu ~ % bzr init-repo --rich-root-pack phpunit
Shared repository with trees (format: rich-root-pack)
Location:
  shared repository: phpunit
sb@ubuntu phpunit % bzr checkout svn+ssh://sb@svn.phpunit.de/var/svn/phpunit/phpunit/trunk

I still use Subversion natively to deal with the release branches:

sb@ubuntu phpunit % svn co svn+ssh://sb@svn.phpunit.de/var/svn/phpunit/phpunit/branches/release/3.4
sb@ubuntu phpunit % svn co svn+ssh://sb@svn.phpunit.de/var/svn/phpunit/phpunit/branches/release/3.3

The bzr info command shows that the local Bazaar branch is related to a remote Subversion branch:

sb@ubuntu phpunit % bzr info trunk
Repository checkout (format: rich-root-pack)
Location:
  repository checkout root: trunk
        checkout of branch: svn+ssh://sb@svn.phpunit.de/var/svn/phpunit/phpunit/trunk
         shared repository: .

Next, create a feature branch and hack away:

sb@ubuntu phpunit % bzr branch trunk feature
Branched 205 revision(s).
(hack, hack, hack)
sb@ubuntu feature % bzr commit -m "blah blah blah"
(hack, hack, hack)
sb@ubuntu feature % bzr commit -m "blah blah blah"
sb@ubuntu trunk % bzr update
sb@ubuntu trunk % bzr merge ../feature
sb@ubuntu trunk % bzr commit -m "Message for SVN commit."

At least for the foreseeable future, I will not migrate the central Subversion repository of the PHPUnit project to Bazaar as Subversion is a good choice for implementing a centralized workflow and is well understood by those of my users that use PHPUnit from a Subversion checkout, for instance using svn:externals to integrate it with their own software configuration management.

December 31, 2008

Sebastian Bergmann

PHPUnit 3.4.0 - Alpha 1

In an effort to end the year on a high note, I have released a first preview release of PHPUnit 3.4 today.

The highlights of this new release series include:

The complete ChangeLog is also available.

PHPUnit 3.4.0alpha1 is not feature-complete and should not be used in production.

Please have a look at the new features and test whether this new version of PHPUnit can run your test suite without problems.

December 29, 2008

Sebastian Bergmann

PHPUnit 3.3.9

  • Fixed #425: Code Coverage fails if array from Xdebug is not sorted. [4370]
  • Fixed #660: PHPUnit_Framework_Assert::getObjectedAttribute() fails for inherited private attributes. [4385]
  • Implemented #659: Implement workaround for PHP bug #46064. [4360]

December 18, 2008

Sebastian Bergmann

PHPUnit 3.3.8

  • Fixed #425: Code Coverage fails if array from Xdebug is not sorted. [4270]
  • Fixed #649: Fatal error: Unsupported operand types in /usr/share/php/PHPUnit/Framework/ComparisonFailure/Scalar.php on line 78. [4287]
  • Fixed #650: PHPUnit tries to include non-existent bootstrap file. [4303]

December 13, 2008

Sebastian Bergmann

PHPUnit 3.3.6

  • Implemented #636: clearstatcache() after setUp() and before test. [4174]
  • Fixed #500: Bump requirement for PEAR package to version 1.7.1. [4198]
  • Fixed #612: Bootstrap file is not included before including test files. [4228]
  • Fixed #628: Mocked static methods cause fatal errors. [4144]
  • Fixed #629: @expectedException does not work with the new namespace separator. [4140]