Behaviour Driven Development

Test Driven Development is a well established programming technique for creating high quality software. It is less known, however, that TDD is not only a programming technique but also a design methodology.

The main goal of Behaviour Driven Development, a TDD based methodology, is to identify behaviours in both the analysis and the design phases.
In BDD [1] the test code looks more like a specification of behaviours than a test of the production code.

Test Driven Development

TDD can be summarized in one rule:
“Writing code is only allowed if you have a failing unit test”.

The TDD development cycle:
1. Write a unit test
2. Run all tests and make sure the new one fails
3. Implement the simplest possible solution in order to make the test pass
4. Refactor the code. All tests must pass after the refactoring has been done.
5. Repeat – write a new unit test

Problems:

  • Unit tests suggest a strong relationship between test class and implementation
    class. Each class or method usually has a corresponding test class or test meth-
    od. This causes a high coupling between the class under test and the test case.
    It also means that we focus too early on the implementation details, instead of
    doing the design first.

  • Unclear definition of granularity of units. A common mistake is to mix up unit test with integration tests – which may require complex setup of several com-
    ponents (like a database). Having a high coupling between test code and the
    implementation is a serious problem when later on refactoring is needed. In-
    stead one should use mock objects to explore interactions between objects.

  • Limitations on mock objects may have too big an impact on the design. We
    often have to stop using the private, static and final keywords. This problem was
    discussed in the previous issue of JayView – Mocking Static Methods.

The Marriage of Component
Specification with Unit Test

BDD has a similar development cycle, but instead of writing tests before coding you
write specifications before coding.
A specification consists of a description of behaviours which are expressed within a
context. Behaviours become self-verifying by writing (coding) expectations in the
form of examples. The specification is written in an executable form so that we can
generate a readable specification and verify that its expectations are valid.

Example

For example let’s write a specification for a stack. We start by identifing its contexts,
which are: “empty”, “neither empty nor full”, “full”. Example of behaviours for the
empty context are: “should be empty”, “should not be empty after a push”. For each
of those one continue to write expectations. Like TDD you specify a small set of
behaviours at a time then implement it – short iterations.
Let’s show how this can be done using standard JUnit since it is a well known
tool. JUnit is not a good tool for doing BDD since it was only designed for doing
testing. A more suitable tool is for example JDave [4] or RSpec [2] which let you
create much more readable specification. (The analysis part of RSpec is shown in
the next section).

By replacing the word “test” with “should” and organizing tests around behaviours it
becomes clear that we are using BDD to drive the design.
This format also allows us to generate an even more readable specification by using
for example the junitreport ant task with a custom style sheet that extracts the bold
words. A proper BDD tool would have this ability built in. I believe this specification
is much better than the (class) javadoc that are often missing or incorrect.
As shown above we keep specification and test together in an executable unit. This
approach can also be used at a system level.

The Marriage of Application
Requirements with Acceptance Tests

Requirements and acceptance tests are captured using a template containing a story
and one or more scenarios.
As a Role, I want Feature, So that Benefit
Scenario1: GivenWhenThen
Scenario2 …
A story’s behaviour is its acceptance criteria – the scenarios. By using the template
above we can collaborate on stories with customers. This is nothing new, it is just
one way of doing analysis.
What is new is that in BDD the specification is written down in an executable
unit in order to have self-verifying tests. The Ruby RSpec tool has a slightly different
approach. It can treat specification written in plain english as an executable unit.

An example of a story:

Story: transfer to cash account
As a savings account holder
I want to transfer money from my savings account
So that I can get cash easily from an ATM
Scenario: savings account is in credit
Given my savings account balance is 100
And my cash account balance is 10
When I transfer 20 from my savings account to my cash account
Then my savings account balance should be 80
And my cash account balance should be 20
Scenario: savings account is overdrawn
Given my savings account balance is -20
And my cash account balance is 10
When I transfer 20 from my savings account to my cash account
Then my savings account balance should be -20
And my cash account balance should be 10

To perform verification on this specification we create an interpreter where we de-
fine reusable test steps.

To run it we need to tell which steps are using what story:

RSpec matches each line in the story with the defined test steps. The code inside the
define block will be executed if a match is found.
For example, when the story runner reads the line “Given my savings account bal-
ance is 100” it will execute

That means a new account object is created and stored in the accounts hash.

Still stuck with Java ? Psst, you can use JRuby [5] to test and mock Java
objects. For example, try the JtestR [6] tool which also integrates nicely
with ant, maven and Buildr [3].

Conclusions

There is not a big difference between TDD and BDD if TDD is used correctly. TDD
often causes brittle test code – a small change in the production code may cause a
major change in the test code. BDD gives the possibility of structuring tests to make
them “refactoring friendly”. This is accomplished by organizing tests in small focused
examples of behaviours.
People are not always aware that TDD is able to drive the design. By not thinking
in terms of tests but instead describing the what and why of behaviours, it becomes
clear that BDD is a methodology for analysis and design.

References

[1] BDD – http://behaviour-driven.org/
[2] RSpec – http://rspec.rubyforge.org/
[3] Buildr – http://buildr.rubyforge.org/
[4] JDave – http://www.jdave.org/
[5] JRuby – http://jruby.codehaus.org/
[6] JtestR – http://jtestr.codehaus.org

Originally published in JayView.

1 Comment

  1. Not Relevant

    I prefer Brain Driven …

Leave a Reply