TheHumbleProgrammer

Just another WordPress.com weblog

Archive for the ‘BDD’ Category

Given you’ve heard of BDD, When you try to get started, Then you will find much confusion and anger.

Posted by thehumbleprogrammer on April 18, 2009

On my last project, as part of a developer wide shift I was introduced to Behaviour Driven Development. BDD has been gathering interest in the test driven community for quite some time. For a good background to this development technique it’s best to start at the beginning and  read Dan North’s article introducing BDD. From this article you can see the intention of BDD is to simplify a test first approach to software development,

I had a problem. While using and teaching agile practices like test-driven development (TDD) on projects in different environments, I kept coming across the same confusion and misunderstandings. Programmers wanted to know where to start, what to test and what not to test, how much to test in one go, what to call their tests, and how to understand why a test fails.

The deeper I got into TDD, the more I felt that my own journey had been less of a wax-on, wax-off process of gradual mastery than a series of blind alleys. I remember thinking “If only someone had told me that!” far more often than I thought “Wow, a door has opened.” I decided it must be possible to present TDD in a way that gets straight to the good stuff and avoids all the pitfalls.

My response is behaviour-driven development (BDD). It has evolved out of established agile practices and is designed to make them more accessible and effective for teams new to agile software delivery. Over time, BDD has grown to encompass the wider picture of agile analysis and automated acceptance testing.

thus lowering the entry level, which will increase take up amongst developers and the quality bar will be increased. Once you have read the article and, like me, felt an overwhelming desire to make the jump from boring old TDD to brand new BDD immediately, you will then mistakenly Google a phrase such as “Getting Started With BDD“. Ignoring the Microsoft articles you will avidly read anything and everything in this search result trying to grok BDD, unfortunately all you will find my friend, is confusion and anger.

In the end you must resist the urge to download any of the BDD frameworks out there until you have gotten your hands dirty writing your own implementation of BDD. Once you have become comfortable with this, by all means move onto a framework that allows you to bake the user stories into the tests rendering them unreadable at a glance etc. It’s your choice, we live in a democracy.

Getting started with BDD the pain free way.

first go to Ben Scheirman’s excellent article outlining the Transition from TDD to BDD, this will give you a clear grounding in making the move. Then have a play around with subclassing Ben’s base class and implementing some BDD test fixtures. Tim and Mike did this in my last company resulting in a nice simple framework that could be rolled out across the developer team with a minimal learning curve. The minimal learning curve is very important if you want take up of BDD, which is what the framework writers have forgotten in trying to cleverly bake trace ability from stories too behaviour into the test suite.

An example of our version of BDD would look like this:

   1: namespace specs_for_SessionManager
   2: {
   3:     public abstract class SessionManager_base_context : Specification<SessionManager>
   4:     {
   5:         protected Mock<ISession> Session { get; private set; }
   6:         protected String SessionName { get; private set; }
   7: 
   8:         protected override void EstablishContext()
   9:         {
  10:             Session = base.Substitute<ISession>();
  11:             Session.Setup(s => s.Close());
  12:             Session.Setup(s => s.BeginTransaction()).Returns(base.Substitute<ITransaction>().Object);
  13:         }
  14: 
  15:         protected override SessionManager CreateSubject()
  16:         {
  17:             return new SessionManager(Session.Object, SessionName);
  18:         }
  19:     }

Here I have my specifications for the SessionManager, I then subclass Bens base class and override the necessary methods to establish a context and create the system under test. I can then go on to create a scenario for different behaviours of the system.

   1: [TestFixture]
   2: public class when_closing_a_session : SessionManager_base_context
   3: {
   4:     protected override void When()
   5:     {
   6:         base.Subject.CloseSession();
   7:     }
   8: 
   9:     [Test]
  10:     public void underlying_session_should_be_called()
  11:     {
  12:         Session.AssertWasCalled(s => s.Close());
  13:     }
  14: }
  15: 
  16: [TestFixture]
  17: public class when_beginning_a_transaction : SessionManager_base_context
  18: {
  19:     protected override void When()
  20:     {
  21:         base.Subject.BeginTransaction();
  22:     }
  23: 
  24:     [Test]
  25:     public void a_transaction_should_have_begun_on_the_underlying_session()
  26:     {
  27:         Session.AssertWasCalled(s => s.BeginTransaction());
  28:     }
  29: }

As you can see we have a test fixture for each scenario, which overrides the when method in order to invoke the system under test in this context. Each test makes some assertion for expected behaviour in this scenario. Note the tests are now just one line assertions, we have split out the arrange and act part of the tests into the base class and the When method. The outcome of all this is a nice report in your resharper test runner like so;

NotQuiteRight_BDD

This is a big step in the right direction, we can see the scenario that we are testing and the outcome of that behaviour being invoked, the only thing we are missing is the given. With the current style I found myself tacking on some context to the class name like so

when_beginning_a_transaction_with_a_pre_existing_transaction

This is not quite right, in my code I want to say Given a transaction is running When beginning a transaction Then an exception should be thrown, I can’t easily do that with the current structure so I tried using the namespace for the given and now my structure looks like this:

   1: 
   2: namespace base_context_for
   3: {
   4:     public abstract class session_manager : Specification<SessionManager>
   5:     {
   6:         protected Mock<ISession> Session { get; private set; }
   7:         protected Mock<ITransaction> Transaction { get; private set; }
   8:         protected String SessionName { get; private set; }
   9: 
  10:         protected override void EstablishContext()
  11:         {
  12:             Session = base.Substitute<ISession>();
  13:             Transaction = base.Substitute<ITransaction>();
  14:             Session.Setup(s => s.Close());
  15:             Session.Setup(s => s.BeginTransaction()).Returns(Transaction.Object);
  16:         }
  17: 
  18:         protected override SessionManager CreateSubject()
  19:         {
  20:             return new SessionManager(Session.Object, SessionName);
  21:         }
  22:     }
  23: }
  24: 
  25: namespace given_a_session_is_open
  26: {
  27:     [TestFixture]
  28:     public class when_closing_a_session : base_context_for.session_manager
  29:     {
  30:         protected override void When()
  31:         {
  32:             base.Subject.CloseSession();
  33:         }
  34: 
  35:         [Test]
  36:         public void underlying_session_should_be_closed()
  37:         {
  38:             Session.AssertWasCalled(s => s.Close());
  39:         }
  40:     }
  41: }

As you can see my base context is now in its own namespace called base_context_for, the base context class name is just the system under test. I can then subclass the base class with a fully qualified name, like so;

public class when_closing_a_session : base_context_for.session_manager

The above signature makes it really easy to see exactly what the system under test is and what the scenario is. 

On line 25 you will see that I have another namespace declaration to wrap the subclass, the namespace becomes the given, the class name is the when and the test methods correspond to then. Giving a nice resharper report like this:

final_bdd

For those of us that like to run TestDriven.Net, we will still get the same output when all is good

5 passed, 0 failed, 0 skipped, took 2.33 seconds.

but if you get a failing test you get the following output:

TestCase ‘given_a_transaction_already_exists.when_beginning_a_transaction.should_throw_invalid_operation_exception’

failed:
  Expected: instance of <System.InvalidOperationException>
  But was:  null

you can clearly see on the top line a full scenario description, which should make it nice and easy to figure out exactly what the issue is.

Conclusion

It is still early days for me and BDD but I am enjoying it and can see the benefit. For me BDD is all about giving an intuitive entry point into test first development, a by product of this is a nice report that developers can quickly see what is going wrong in their system under certain conditions. I think that trying to bake the full user story into the system at all levels of testing is a recipe for disaster. The frameworks for BDD seem to be geared towards the being able to trace a user story to some behaviour in your system. This leads to confusion for the developer, long overly noisy tests peppered with unmaintainable strings. The transition is now complete from TDD to BDD, until I have more experience in writing Behaviour fixtures I will stick to this structure. I would love to hear any of your thoughts (not you mum, my other reader, cheers big bro) on this structure and how it can be improved.

Posted in BDD, Unit testing | 5 Comments »