Spec BDD PHPUnit Flow: Symfony2 Behat aftermath

What to do right after a Spec-type BDD feature was written in behat and it is on red failing state?

It is certainly time to connect it with the Spec-type BDD counterpart on PHPUnit so that we can start dumping our specification on a phpunit class.

I will give you a tip on how to get a quick start-up on writing the your first PHPUnit class by writing a first design class. Is it really going back again to write the design first? No. So don’t worry.

But we will write firstly the design in a BDD oriented way according to a set of two specifications like this:

<?php
class Example {
    public function applyPenaltyWhenMissingPapers() {
        return true;
    }
 
    public function applyPenaltyWhenDamageIsPresent() {
        return true;
    }
}

This is not the final class that I am aiming at designing. Rather this is a step towards getting quickly up to speed with the specification into php code.

So I run this command to generate my first phpunit class:

phpunit --skeleton-test Example Calculator/Example.php

Were it not for the “test” word the command below would have generated the phpunit class that I wanted:

<?php
require_once '/home/cordoval/sites-2/FormModelProjectBundle/vendor/bundles/Cordova/Bundle/FormModelBundle/Calculator/Example.php';
/**
 * Test class for Example.
 * Generated by PHPUnit on 2011-07-27 at 12:59:50.
 */
class ExampleTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Example
     */
    protected $object;
 
    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp()
    {
        $this->object = new Example;
    }
 
    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown()
    {
    }
 
    /**
     * @todo Implement testApplyPenaltyWhenMissingPapers().
     */
    public function testApplyPenaltyWhenMissingPapers()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
          'This test has not been implemented yet.'
        );
    }
 
    /**
     * @todo Implement testApplyPenaltyWhenDamageIsPresent().
     */
    public function testApplyPenaltyWhenDamageIsPresent()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
          'This test has not been implemented yet.'
        );
    }
}
?>

Then one can run a find replace using a regexp (If you know a good one to replace all please let me know) and change the word test for should:

<?php
 
require_once '/home/cordoval/sites-2/FormModelProjectBundle/vendor/bundles/Cordova/Bundle/FormModelBundle/Calculator/Example.php';
 
/**
 * Test class for Example.
 * Generated by PHPUnit on 2011-07-27 at 12:59:50.
 */
class ExampleTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Example
     */
    protected $object;
 
    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp()
    {
        $this->object = new Example;
    }
 
    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown()
    {
    }
 
    /**
     * @test
     * @todo ImplementshouldApplyPenaltyWhenMissingPapers().
     */
    public function shouldApplyPenaltyWhenMissingPapers()
    {
        // Remove the following lines when you implement this spec.
        $this->markTestIncomplete(
          'This spec has not been implemented yet.'
        );
    }
 
    /**
     * @test
     * @todo ImplementshouldApplyPenaltyWhenDamageIsPresent().
     */
    public function shouldApplyPenaltyWhenDamageIsPresent()
    {
        // Remove the following lines when you implement this spec.
        $this->markTestIncomplete(
          'This spec has not been implemented yet.'
        );
    }
}

Note that in addition to our changes we have also added the @test tag to identify methods as tests since we are not prefixing the methods with “test” word anymore.

And now we are ready to implement the more inner parts of the specification. We also have our starting point of the Example class in which we should get rid of the initial methods and try to define them according to the requirements pass/fail of the new phpunit specification class.

$ phpunit Calculator/ExampleTest.php 
PHPUnit 3.5.14 by Sebastian Bergmann.
 
II
 
Time: 0 seconds, Memory: 5.75Mb
 
OK, but incomplete or skipped tests!
Tests: 2, Assertions: 0, Incomplete: 2.

Notice the I is for incomplete. And our design process continues. Until we get:

PHPUnit 3.5.14 by Sebastian Bergmann.
 
..
 
Time: 0 seconds, Memory: 5.75Mb
 
OK (2 tests, 2 assertions)

And of course a nice formatted output like:

phpunit --testdox Calculator/ExampleTest.php 
PHPUnit 3.5.14 by Sebastian Bergmann.
 
Example
 [x] Should apply penalty when missing papers
 [x] Should apply penalty when damage is present

After we have finished designing we can run the command above again and save our Test class with another name since that will work with the Spec BDD features of behat. The new Test class will be a more thorough test class which will ensure regular unit testing. But it is encouraged that these two classes end up being similar so to save work and provide a good design practice.

Hope this helps!

Leave a Reply

Your email address will not be published. Required fields are marked *