nosewheelie

Technology, mountain biking, politics & music.

What is Behaviour Driven Development?

with 6 comments

I’ve been reading a lot about BDD of late, mainly from the .Net community and mainly about story-level BDD, mostly driven by RSpec and NBehave. I finally got around to writing my take on BDD, and have had a paper accepted at the Open Source Developers’ Conference coming up in November. The following is an excerpt from my paper, the full text of my submission is available as a PDF.

What is Behaviour Driven Development?

“The act of writing a unit test is more an act of design than of verification. It’s also more an act of documentation than of verification. The act of writing a unit test closes a remarkable number of feedback loops, the least of which is the one pertaining to verification of function.” Robert C. Martin

Behaviour Driven Development (BDD) is a development practice arising out of agile development methodologies, first developed by Dan North in response to the problems experienced using and teaching TDD [10]. At its core, BDD is a refinement to TDD that shifts the emphasis from testing to specification and is in effect the best practices of what developers practising TDD have been doing all along. While this doesn’t seem like a major change, the shift in emphasis from testing to specification brings a number of important flow on effects that positively impact the development of both test and production code. The following sections describe these effects.

Ubiquitous Language

For many, the language used to express a concept has an impact on the way they think about that thing. Goh states that the “abstractions and concepts you use to express yourself in any language … shape the way you think about the problem you are solving” [5]. This is supported in linguistics by the Sapir-Whorf hypothesis which postulates that there is “a systematic relationship between the grammatical categories of the language a person speaks and how that person both understands the world and behaves in it” [18]. For software development, this implies that the language we use to describe the software constructs has an impact on how we create those constructs; by changing the language we affect the code we create. As a concrete example, consider that this line of reasoning is used to justify assigning meaningful names to functions and variables. Also, developers implicitly feel the impact of language when working with a well designed API; an API that provides well named classes and functions within a well designed architecture.

BDD supports using meaningful language in two ways. Firstly, it focuses on “getting the words right”, encouraging good naming of classes, methods and variables. Secondly, it borrows concepts from Domain Driven Development (DDD) to bridge the gap between technical and business artefacts [3]. BDD attempts to capture the behaviour of the domain using a clear and concise syntax that everyone can understand, forming consensus around not only the domain artefacts but also the run-time behaviour of the system [13, 16]. BDD calls the shared language used by all stakeholders the ubiquitous language of the domain.

Design Focus

“A waterfall ‘designer’ starts from an understanding of the problem and builds up some kind of model for a solution, which they then pass on to the implementers. An agile developer does exactly the same, but the language they use for the model happens to be executable source code rather than documents or UML.” Kerry Buckley

TDD advocates acknowledge that one of the most important outcomes of practising TDD is its influence on the design of the resulting code. Test driven code has less defects [7] than non-test driven code and is often more cohesive and less coupled than non-test driven code. However the emphasis on “testing” limits TDD’s uptake and effectiveness in driving design (from both a managerial and technical point of view). BDD acknowledges that design is one of the most important outcomes of testing by providing language and tools that support the creation of well-designed code.

Behaviour Focus

“So if it’s not about testing, what’s it about? It’s about figuring out what you are trying to do before you run off half-cocked to try to do it.” Dave Astels

The difference between testing and specifying may be subtle, but it leads to an increased focus on the behaviour of a piece of code. By focusing on behaviour, BDD frameworks break the traditional 1-to-1 mapping of a unit test class to a production class. The location of the behaviour is no longer important, resulting in test code that is less coupled to its production counterpart and less fragile when production code is refactored. Rather than a 1-to-1 mapping, BDD encourages an M-to-N mapping, allowing as many specification classes as needed to specify the required behaviour. Furthermore, behaviour contexts provide the ability to group related specifications into a single class. Contexts are usually created around different states of an object, such as an empty and non-empty stack. A single context focuses on one thing, thereby reducing the confusion of having multiple states (of a subject) and multiple assertions in a single test.

Figure 1 shows several problems encountered test-driving, and identifies the BDD practices and Instinct features that address the problem.

TDD Problem Matrix

Figure 1. Problems with traditional TDD that BDD and/or Instinct overcome.

BDD Frameworks

Early BDD frameworks focused on acceptance or story-level behaviour. Frameworks such as JBehave [6] allow an application’s behaviour to be described in terms of stories and scenarios. Subsequent frameworks such as RSpec [15] (for Ruby) and NSpec [12] (for C#) focused more on the code level of testing, offering an xUnit equivalent feature set for low level specifications. Both approaches are legitimate, and use ubiquitous language to describe the desired behaviour of the system at the appropriate level.

Story-level frameworks provide APIs to allow business stakeholders (e.g. XP’s Customer, Scrum’s Product Owner, business/functional analyst or traditional QA tester) to understand the behaviour of the system. Typically these frameworks use the “as a/i want/so that” form of story definition and “given/when/then” form of test lifecycle, and also provide an API to plug in the implementation of the acceptance test (the code that supports the wording). Listing 1 shows a story-level specification in Ruby.

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) do

  Scenario "savings account is in credit" do
    Given "my savings account balance is", 100
    Given "my cash account balance is", 10
    When "I transfer", 20
    Then "my savings account balance should be", 80
    Then "my cash account balance should be", 30
  end

  Scenario "savings account is overdrawn" do
    Given "my savings account balance is", -20
    Given "my cash account balance is", 10
    When "I transfer", 20
    Then "my savings account balance should be", -20
    Then "my cash account balance should be", 10
  end
end
Listing 1. Ruby BDD story framework (RBehave) [11]

Code-level frameworks provide APIs that allow developers to design and specify the behaviour of low level components of the system. These frameworks provide xUnit equivalent feature sets and support ubiquitous language by encoding it into the APIs used to describe the expected behaviour of a system, as well as the interaction between the specification code and the BDD framework itself. The APIs used for describing expected behaviour typically take the form of Domain Specific Languages (DSLs) or fluent APIs. Consider the following abridged code samples from the Ruby framework RSpec and the C# framework NSpec.

describe "non-empty Stack" do
    it "should return the top item when sent #peek" do
        @stack.peek.should == @last_item_added
    end
end

[Specification]
public void NSpecSpecificationExample() {
    Specify.That(someObj.Foo()).ShouldEqual(someOtherObj);
    Specify.That(someObj.GetSomeFloat()).ShouldEqual(5.3)
        .WithAToleranceOf(0.1);
    Specify.That(someObj.SomeMethod()).ShouldBeNull();
    Specify.That(someObj.Bar()).ShouldBeOfType(typeof(Foo));
}
Listing 2. RSpec & NSpec behaviour specifications.

BDD frameworks also make use of meaningful naming and readability when defining the way a developer interacts with the framework. They provide flexible, explicit and meaningful ways of defining specification methods and classes. Owing to the flexibility of the language, Ruby frameworks set the standard on readability. Java and C# frameworks simulate the freedom provided by more flexible languages by exploiting generics, chained method calls and method naming techniques.

Listing 3 shows the same specification using RSpec syntax and Instinct syntax respectively, highlighting the readability provided by the framework syntax. In these examples the specification should be read as “a non-empty Stack should return the top item when sent peek”.

describe "non-empty Stack" do
    it "should return the top item when sent #peek" do
        @stack.peek.should == @last_item_added
    end
end

class ANonEmptyStack {
    void shouldReturnTheTopItemWhenSentPeek() {
        expect.that(stack.peek()).equalTo(lastItemAdded);
    }
}
Listing 3. Behaviour specifications using RSpec and Instinct.

BDD Terminology

As BDD focuses on “getting the words right”, it introduces subtle changes to the traditional TDD vocabulary. BDD frameworks such as Instinct also adopt the terminology introduced by Meszaros [9]. The major concepts introduced in BDD are defined below.

Specification
A method/function in which the behaviour of a piece of code is specified. Specifications are executable examples that guide the design process and provide both documentation and tests. Specifications are analogous to test methods in xUnit frameworks.
Context
A context in which a certain behaviour is valid. Contexts can be used to group specifications together and also to set up the state in which expectations hold.
Collaborator
An object that interacts with another object, providing a service to it. Collaborators are usually mocked or stubbed out in specifications in order to verify interactions between them and the subject.
Actor
An actor is an object that has a role in a specification. Subjects, dummies, stubs and mocks are all actors.
Subject
The class whose behaviour is under scrutiny.
Double
An implementation of an interface (or extension of a class) that is only used for testing. Doubles can be manually created (plain classes that implement an interface) or auto-created via a framework.
Dummy
Dummy objects are passed around but never actually used, they are usually used just to fill parameters to simplify specifications (where their behaviour may not be important). Dummies will throw exceptions if methods are called on them. They are the simplest form of test double implementation.
Stub
Stubs respond to method calls made during a test by providing canned answers. Stubs may record information about calls, such as an email gateway stub that remembers the messages it ‘sent’. Stubs do not fail if methods are called or the order in which they are called (if at all).
Mock
Mocks are more advanced stubs, that not only respond to calls made during a test but are also pre-programmed with expectations which form a specification of the calls they are expected to receive. Mocks will throw an exception if they receive a call they weren’t expecting and are checked (called verification) to ensure they received all the calls they expected. Some mocks also verify the order of calls made.
Fixture
A fixture is a known set of data (or commands to setup that data) that provide the environment for a set of tests. Fixtures work well when you have a bunch of tests that work on similar data reducing the complexity of your testing environment (fixtures can also have a downside when overused between tests that should have independent data).

Further Reading

Read the full paper from which this excerpt was taken.

References

  1. Apache Ant, http://ant.apache.org/, 2007.
  2. Astels, D., A New Look at Test-Driven Development, http://blog.daveastels.com/files/BDD_Intro.pdf, 2005.
  3. Bellware, S., Behavior Driven Development is…, http://codebetter.com/blogs/scott.bellware/archive/2007/08/04/166415.aspx, 2007.
  4. Buckley, K., Concurrent design and development – a better spin?, http://www.kerrybuckley.com/2007/09/26/concurrent-design-and-development-a-better-spin/, 2007.
  5. Goh, T., TDD vs BDD, http://www.progprog.com/articles/2007/08/17/tdd-vs-bdd, 2007.
  6. JBehave, 2007, http://jbehave.org/, 2007.
  7. Jeffries, R. and Melnik, G., TDD: The Art of Fearless Programming, IEEE Software, http://www.computer.org/portal/cms_docs_software/software/homepage/2007/s3024.pdf, 2007.
  8. jMock – A Lightweight Mock Object Library for Java, http://www.jmock.org/, 2007.
  9. Meszaros, G., xUnit Test Patterns: Refactoring Test Code, Addison-Wesley, 2007.
  10. North, D., Introducing BDD, http://dannorth.net/introducing-bdd/, 2006.
  11. North, D., Introducing rbehave, http://dannorth.net/2007/06/introducing-rbehave, 2007.
  12. NSpec, http://nspec.tigris.org/, 2007.
  13. Ocampo, J., Comment on Adverbs – A Partial Obstruction to BDD, http://codebetter.com/blogs/scott.bellware/archive/2007/09/09/167744.aspx, 2007.
  14. QuickCheck: An Automatic Testing Tool for Haskell, http://www.cs.chalmers.se/~rjmh/QuickCheck/, 2007.
  15. RSpec 1.0.8 Examples, http://rspec.rubyforge.org/examples.html, 2007.
  16. Sahayam, S., Behaviour-Driven Development (BDD) – A first look, Workingmouse Internal Blog (not publically available), 2007.
  17. TestDox, http://agiledox.sourceforge.net/, 2007.
  18. Wikipedia, Sapir–Whorf hypothesis, http://en.wikipedia.org/wiki/Sapir-Whorf_hypothesis, 2007.

Written by Tom Adams

October 14th, 2007 at 8:44 pm

Posted in BDD,Instinct,Java,Ruby,TDD

6 Responses to 'What is Behaviour Driven Development?'

Subscribe to comments with RSS or TrackBack to 'What is Behaviour Driven Development?'.

  1. Great write up! Thanks!

    That said…

    You’re categorization of the “unit level” specifications is misleading.

    There’s no value in talking about these “unit level” specifications in absentia of the stories that caused them to come into existence.

    The spec on the stack object is typical of unit testing and TDD tutorials and does negative service to BDD practices since unit testing and TDD examples are often presented out of context with their stories.

    I think you’ve just fallen into the same old TDD trap except that here you’re doing it with a BDD-oriented tool.

    Scott Bellware

    15 Oct 07 at 6:21 am

  2. Excellent writeup! I love your matrix.

    Joe Ocampo

    15 Oct 07 at 1:40 pm

  3. @Joe. Thanks. The matrix was much larger, it represented all the problems I’ve encountered using TDD on projects over the last 3 so years. Unfortunately not all of these are addressed by BDD so I was unable to include them in the matrix. I’m still searching for solutions for these issues.

    @Scott. Thanks for the positive comments, it was yours and Joe’s blogs that I’ve been reading for the last little while. The .Net (and Ruby) community seems to be more active in this area than Java’s.

    I make the distinction between “code” and “story” levels as I find that current “BDD” frameworks are focused at one or the other (unfortunately not usually both). Hopefully this distinction will go away after a while (we’re already seeing RSpec/RBehave), and we’ll see frameworks support both (all) levels.

    I personally came to BDD after seeing RSpec, and seeing how it overcame a lot of the problems I’d had test driving. From that point of view I created Instinct to help in driving behaviour from a developer’s POV. It’s only been in more recent times that I’ve seen the emphasis (on blogs at least) shift back to story level specification. I think this is a *good thing*, however at some point developers need to be able to specify behaviour at their level.

    We are all customers of our own code and we all need an API that provides the right language. Code level frameworks provide this for the developer, story level frameworks for a discussion between developers and customers.

    Is it the example I’ve given or the categorisation that you’re not comfortable with. Upon re-reading, perhaps it’s the lack of context?

    I’ve no problem with BDD examples being presented in context with the stories that drive them, however I felt the examples (possibly presented out of context) were appropriate for the audience of OSDC. Also, there is every possibility that these high level stories will drive a large number of lower level artefacts (classes, etc.) that may be technical in their nature, and not something of interest to a customer. Unfortunately, I don’t believe that the current story level APIs provide the flexibility nor readability required by developers when specifying the behaviour of this code.

    I’m not particularly enamoured of the example, I think a stack is a pretty poor example for BDD, so I’d be happy for a better one!

    Tom Adams

    15 Oct 07 at 9:03 pm

  4. +1 for Joe’s comment. Great post Tom.

    Tim Haughton

    15 Oct 07 at 10:08 pm

  5. Thanks Tim.

    Tom Adams

    16 Oct 07 at 1:07 pm

  6. [...] The weaker Sapir-Whorf hypothesis, also known as “Linguistic Relativism”, proposes that the “facilities” of your language influence the kinds of thoughts that you will have, that your thoughts are effectively guided in a certain direction based on the language you are using. This is well-known to Rubyists, particularly in the RSpec/BDD world, so I won’t talk too much about that in this article. There are many other articles covering the interactions between RSpec and Sapir-Whorf and BDD. [...]

Leave a Reply