Starting with BDD vs. starting with TDD

Yesterday I did a presentation on TDD/BDD at the Tamp Code Camp. I have done several TDD presentations in the past but this was the first time I also showed the attendees BDD at the same time. In actuality I didn’t even show them a traditional TDD test. Not to my surprise, newcomers seem to grasp BDD much quicker and easier than from a TDD perspective. I did touch on that some tests would still be driven from a technical aspect, but from a business requirements they should try to use BDD. Another thing I very briefly touched on was Mocks/Stubs. I try not to go too in depth as you can discuss mocks and stubs for an hour by themselves and isn’t worth it to dive into when all you have is an hour.

The best description I came up with for what is "BDD", it’s nothing more than two things:

  1. A language shift in traditional TDD
  2. Driving your tests from a domain/user story perspective rather than technical perspective
When this was explained to a group of people that have never even used TDD, their heads nodded and I saw about 30 lightbulbs come on in the room. They just seemed to "get it" right away.
As I dive further into a description here. I should note that there is ALOT of differing opinions on what the proper way to do BDD is and what the proper “language” is. Much like TDD, it comes down to personal preference. Using a simple BDD tool like SpecUnit helped me a lot to figure out how to structure my tests in the beginning. From there, It breaks down to what you find works.
 
SpecUnit lays a pretty good foundation on what your language is. Let’s take a look at the language real quick. We’ll compare traditional TDD test naming vs. BDD test naming. Here’s how you would layout a test class and test for an AddressBook application with traditional TDD:
 
[TestFixture]
public class addressbook_tests
{
    [SetUp]
    public void SetUp()
    {
        // setup code for test
    }
 
    [Test]
    public void can_add_person_to_addressbook()
    {
        // test assertions
    }
}

As you can see. We have TestFixture/Test attributes. This is pretty straightforward and if you’ve been doing TDD you know how it works. Now let’s look at the same test using SpecUnit and with BDD language adjustments:

[Concern("Address Book"), TestFixture]
public class when_adding_a_person_to_an_addressbook : ContextSpecification
{
    [Context]
    protected override void  Context()
    {
        base.Context();
 
        // setup code for test
    }
 
    [Observation, Test]
    public void addressbook_contains_person()
    {
        // test assertions
    }
}

Its a minor shift but a couple of things are important here.
  1. I have both Concern/TestFixture and Observation/Test attributes on the class/method. This reason I am doing this is because I am using Resharper. At the moment, resharper doesn’t recognize that Concern/Observation derive from TestFixture/Test and thus needs to be added so the Resharper test runner recognizes the tests. I have filed a bug with JetBrains and this will be fixed on the next release. It also helps to show what was a testfixture and test in the first example
  2. Instead of [SetUp] attribute you now have the [Context] attribute.
  3. There are other methods you can override from ContextSpecification like “Context_BeforeAllSpecs”, “Context_AfterAllSpecs” and so on.
  4. SpecUnit has a number of extremely useful extension methods that make for a much more readable assertions like: somevalue.ShouldEqual(“whatever”).

In BDD one of the biggest shifts is that your testfixture classes are now grouped together into “Concerns” and your classes are broken out into Contexts. So in the TDD example our individual tests defined the context, now we pull that context up to the class level and the tests then become the acceptance criteria for the context.

BDD has a much better alignment with business concerns and allows us to create tests that are parallel with User Stories/Acceptance criteria. This allows us to write software that is directly inline with what our stakeholders want rather than writing code that may or may not be necessary.

Moving on, lets look at another important part of BDD which has to do with reusing contexts in your tests. Ok, so lets say we are creating an addressbook in our “when_adding_a_person_to_an_addressbook” like so:

[Concern("Address Book"), TestFixture]
public class when_adding_a_person_to_an_addressbook : ContextSpecification
{
    private AddressBook addressBook;
 
    [Context]
    protected override void  Context()
    {
        base.Context();
 
        addressBook = new AddressBook();
    }
}

Now lets say we have another user story and we have to create another context for “when_searching_for_a_person_in_an_addressbook”. Instead of creating a class with a context setup that matches the one above, we want to enforce DRY and create a “behaves_like_addressbook” class that both test classes can utilize:
 
public class behaves_like_addressbook : ContextSpecification
{
    protected AddressBook addressBook;
 
    protected override void Context()
    {
        base.Context();
 
        addressBook = new AddressBook();
    }
}

Now both of the context test classes can derive from this class like so:

[Concern("Address Book"), TestFixture]
public class when_adding_a_person_to_an_addressbook : behaves_like_addressbook
 
[Concern("Address Book"), TestFixture]
public class when_searching_for_a_person_in_an_addressbook : behaves_like_addressbook

So now any setup of the context that our classes share can be placed in the behaves_like_addressbook “Context Base class”. This is a part of bdd that comes from rspec. The ruby guys reuse their contexts in exactly this way. Then if you have additional context base classes along the way if you have two or more contexts that share behavior/setup. For instance. lets say we had a shared context further down we can set it up like this:

public class behaves_like_address_book_with_some_other_context : behaves_like_addressbook
{
    protected override void Context()
    {
        base.Context();
 
        // modify our context that was
        // created in behaves_like_addressbook
    }
}

This really helps to promote reuse among the context setups in your tests. Also take a look at the SpecUnit.report.exe in the specunit project. It allows you to generate an html document from the name of your tests to hand to stakeholders. Very useful form of documentation.

Thats it for an introduction to bdd and to get the gist of it. Now heres a list of resources to get you started not only for the people that were in my presentation yesterday but also for any newcomers to BDD.

SpecUnit : BDD testing tool that was described in this post

schambers googlecode : My google code repository with my resharper templates and AddresBook sample for BDD

AutoHotKey : install this and execute the “TestNamingMode.ahk” from my google code repository, then you do crtl+shift+u to turn on test naming mode where spaces are turned into underscores for you. Thanks to jpboodhoo for this!

Jean-Paul Boodhoo’s Blog : this guy is a BDD master. He has excellent posts on BDD and if your not already, you should definately read his blog.

JetBrains ReSharper : alot of the people in my presentation were blown away when I showed them what resharper was capable of. For anyone that is interested you can obtain a 30-day trial

Any feedback would be greatly appreciated! till next time

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Sean Chambers

I am a Senior software developer from Palm Coast, Florida. An advocate of Domain Driven Design, Behavior Driven Development, creator of FluentMigrator and community activist. I am married to my beautiful wife Erin and am the proud father of two wonderful children. I currently reside at ACI, a local insurance industry/mortgage software company that excels in creating solutions using Agile methodologies.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.lostechies.com/members/colinjack/default.aspx colinjack

    “So in the TDD example our individual tests defined the context, now we pull that context up to the class level and the tests then become the acceptance criteria for the context.”

    I’m not 100% sure this is accurate, I definitely used several approaches before Astels popularized this style of BDD, the fixture based approach was one he’d already popularized in his book “test-driven development” but I like the entire list of approaches in XUnit Test Patterns (http://xunitpatterns.com/Testcase%20Class%20per%20Fixture.html).

    Only making this point because I spent some time talking to a Ruby guy a week or so ago and he said he dislikes the whole BDD term as it is just TDD done well and I have to say I agree.

    “BDD has a much better alignment with business concerns and allows us to create tests that are parallel with User Stories/Acceptance criteria. This allows us to write software that is directly inline with what our stakeholders want rather than writing code that may or may not be necessary.”

    Again I’m not so sure, I mean yes it can but TDD was never about User Sotries/Acceptance criteria and neither is BDD at this level. To me what your describing here is great and you can of course use that approach to structure your acceptance tests but I find the scenario based approach more natural when it comes to acceptance testing.

    I’m thus interested in Cucumber because it seems to have the Dan North style scenario oriented approach and the FIT style approach (http://github.com/aslakhellesoy/cucumber/wikis) in one framework. Yummy.

  • http://www.JeremyJarrell.com Jeremy Jarrell

    Thanks Sean. I’ve been a hardcore TDD user for about 2 years now and I’ve been trying to get my head around BDD but I just haven’t been able to yet. This is the first post I’ve seen that’s actually started to make sense to me.

    Thanks for taking the time to write this post.

    Jeremy

  • http://www.lostechies.com/members/schambers/default.aspx schambers

    @Jeremy, glad I could shed some light. My pleasure!

    @Colin, dude, you need to blog about that stuff. I may be doing it wrong but from examples i’ve seen and what works for me it seems to be going well. There seems to be a great lack of blog posts on BDD styles. PLEASE write some! the community would eat it up. Your comment there could have been a blog post by itself!

  • http://www.lostechies.com/members/colinjack/default.aspx colinjack

    @schambers
    Will do :)

    Also forgot to say, great blog post. We’re going to use this style on a new project so its great to see practical guides that you can point people at.

  • Thomas Eyde

    I have a small issue with the base context class: In my opinion, it hurts readability.

    In this case, when I open the when_adding_a_person_to_an_addressbook fixture/concern in the shared context scenario, I can see:

    - A shared context, but not what it is.
    - All tests/observations refer to an addressBook, but not what it is, nor its expected state.

    A slightly better approach, for me at least, is to move common setup methods up to the base, but keep all declarations in the fixture itself:

    public class behaves_like_address_book_with_some_other_context : behaves_like_addressbook
    {
    private AddressBook addressBook;

    protected override void Context()
    {
    // I want to see what the context really is…
    // base.Context();
    addressBook = base.CreateEmptyAddressBook();
    }
    }

  • http://www.lostechies.com/members/schambers/default.aspx schambers

    @Thomas,

    That is actually is right on point. I was saving that for the next post because i do the same exact thing. Thanks for pointing that out!

  • http://frazzleddad.com Jim Holmes

    As I said over IM, excellent post!

    You ought to do a separate post and show the report generated on the Concern -> Context -> Observation. That’s a wonderful tool for sharing with larger teams (PMs, customers, stakeholders, etc.) to show them how the system behaves and what’s being tested. Pure goodness.

  • Ronald S Woan

    I think the key that most developers around here have a tough time with is that in BDD you should start with user stories from the business owner perspective and from there create specs at the highest level possible and drive them down to more granular tests.

    It is then useful that your spec/test framework allows you to codify these specs in an executable form that allows you to know that your code base or artifiacts are satisfying the stories and implementing the spec.

    Or at least this is what I think Aaron Jensen and Scott Bellware have been expousing in our Seattle Alt.Net meetings.

    I have to admit that I am not all the way there yet, but Aaron did suggest that for teams that have not implemented TDD, skipping directly to BDD might be simpler than gradual transition.

    Aaron covers some of these points in his blog around mspec:

    http://codebetter.com/blogs/aaron.jensen/default.aspx

  • http://www.jimzimmerman.com Jim Zimmerman

    I was at that talk and you did a great job! I ended up coding up a new prototype of a new project all using BDD, resharper, your AutoHotKey script that night for 3 hours. I know, pretty geeky, but watching football all day or night does not really teach you anything new. :)

  • http://scottic.us Scott Bellware

    Colin,

    I don’t think Dave Astels popularized this particular approach to using spec frameworks. He created a framework, but the specific practice and test pattern came significantly later from other sources.

  • http://scottic.us Scott Bellware

    Sean,

    > addressbook_contains_person

    It’s a bit superfluous to mention addressbook again since it is the stated subject (concern) of the context.

  • http://scottic.us Scott Bellware

    Ronald,

    Without getting into the user story thing, I specifically have said to write specifications in the language of the experience of the software rather than the implementation of the software.

  • http://www.lostechies.com/members/colinjack/default.aspx colinjack

    @Scott
    Sorry should have been clearer, I just mean he popularized the TDD->BDD effort and I thought he was involved in the RSpec effort.

  • http://www.claudioperrone.com/blog Claudio Perrone

    Hi Sean,
    “BDD has a much better alignment with business concerns and allows us to create tests that are parallel with User Stories/Acceptance criteria.” As Colin said before, I don’t think this is really true at this unit level. BDD is a bit overloaded these days, in my opinion, as it seems to mean different things to different people.
    The cucumber approach fits that sentence a lot better (although I’m not sure about the need/opportunity for a FIT-style integration yet). You may find interesting a post I wrote about MisBehave, which (I will move it forward over Christmas): http://www.claudioperrone.com/blog/articles/2008/11/09/misbehave-01-oslos-mgrammar-for-bdd-executable-specifications/

  • http://www.sykespro.com Daniel Sykes

    Thanks once again Sean this is a great post! Keep’em coming

  • http://meltitoff.org/ Mitch

    Although I can see the benefits of BDD when moving forward, I too have a hard time wrappin my head around it. However, after what Sean put up, I can @ least start to see some of the syntex in action: Pointing at an executable to make up html on-the-fly is nifty.

  • http://www.meltitoff.org/ Mitch

    can see the benefits of BDD when moving forward, however I too have a hard time wrapping my head around it. However, after what Sean put up, I can @ least start to see some of the syntex in action: Pointing at an executable to make up html on-the-fly is nifty.