Select Page

As appealing as Test Driven Development (TDD) appears, in the workplace, I have yet to be able to see it successfully applied consistently. According to the book The 7 Habits of Highly Effective People, effective habits are defined by the intersection of 3 components; knowledge, skill and desire. Given this, the hypnosis is, if all concepts of habits are explored in a TDD perspective, one would be able to effectively perform TDD.

Knowledge – What to do, why to

Test Driven Development is a development process which starts by creating failing tests first, unlike the traditional approach which is to develop then test or skip the test.

The standard workflow of TDD is:

  1. Create a failing test
  2. Code until the test passes
  3. Refactor the code

When tests are the first aspect of a feature, tests also become a tool of design rather than just verification.

Tests allow the developer to gain empirical feedback. As the developer deploys work, the developer is able to assert their assumptions and measure the progress of the task by executing tests and learning from the results.

Once a test has passed, refactoring code is possible since it is possible to ensure that the refactoring has not changed the behaviour of the code.

Skills – how does this work?

For the purpose of this document, I have chosen Zend Framework and PHPUnit to demonstrate how testing works. The simple project is to create a person who can greet others. By that, I mean say “hello world!”

Following the standard work-flow. Step one is to create a failing test.

…/tests/application/Models/TestPerson.php

<?php

namespace Models;

class PersonTest extends ModelTestCase
{
    public function testGreet()
    {
        $person = new Modelsperson();
        $result = $person->greet();
        $expectedResult = 'Hello World'
        $this->assertEquals($result, $expectedResult);
    }
}

Although it was simple, design choices have been made. I have decided on the name of the class, the function name and its inputs and outputs. There is a clear contract on how this behaviour should operate. Step one is now complete and as we run the PHPUnit test for this feature we expect errors!

Fatal error: Call to undefined method ModelsPerson::greet() in /tests/application/Models/PersonTest.php on line 10

Next, begin developing the feature so that the test passes. The design has been done and all that is left is to lay the bricks. As the task is developed, use the test to continuously assert that the work is complete. Typically, the following output is what you should see:

FAILURES!
Tests: 1, Assertions: 0, Errors: 1.

Starting with a blank canvas:

…/application/Models/Person.php

I begin to develop until finally step two is complete with the following result from PHPUnit:

OK (1 test, 1 assertion)

…/application/Models/Person.php

<?php
namespace Models;

class Person
{
    public function greet()
    {
        $greeting = 'Hello World!';
        return $greeting;
    }
}

The final step enables the developer an opportunity to refactor code without fear of introducing bugs. I have made a trivial refactor to reduce the line numbers.

…/application/Models/Person.php

<?php
namespace Models;

class Person
{
    public function greet()
    {
        return 'Hello World!';
    }
}

Again, we need to verify that nothing has broken by running the tests again and ensure that we are greeted with:

OK (1 test, 1 assertion)

Desire – As a developer, I want to test because…

There are a number of reasons why we want to to be guided by tests when programming. Tests allow us to assert our assumptions against reality. Tests increases our confidence levels in the code behaving as we expected and as it grows through regression testing. When tests are written first, they disrupt the fundamental understanding of testing which is not only to prevent bugs but to also use it as a design tool. However if you do not already have a burning desire to write tests first, it all comes down to acknowledging that all we have to lose is bugs.

Share This