Behavior-Driven Development (BDD) – Setting up Visual Studio/Team Foundation Server (TFS)

In my earlier post, I defined what Behavior-Driven Development (BDD) was and threw in a code example using RhinoMocks.   Hopefully, I was able to inspire some of you out there.  In the event that I did and you will actually attempt to adopt this methodology in your enterprise, I will walk you through the steps required to smoothly integrate this into your existing development environment.

What You Will Need

  • Microsoft Visual Studio 2008 or 2010 Test Edition or above
  • Team Foundation Server
    • This is optional if you want to into take advantage of MSBuild running your tests on check-in.
  • RhinoMocks – (Download Link)
  • TestDriven.NET – (Download Link)
    • This is also optional.  TestDriven.NET is an add-in testing component for Visual Studio that makes running your tests a breeze.
    • The personal edition is free for open source users, trial users, and students.

Step 1 – RhinoMocks
Download RhinoMocks.  The zip file does not contain an executable.  It’s just a library that you will reference in your project.  You can put it in a new directory someone on C:\ for now.

Step 2 – TestDriven.NET
Download and install.  Again, this is an optional component but you should definitely give it a “test drive” and decide, if you are in a company setting, whether you want to purchase a license.  It my example, I will be using MSTest, but it supports multiple test frameworks like NUnit.

Step 3 – Create an empty C# class library project

This will be the project you will be testing against.  You can add it to source control if you have a connection to Team Foundation Server.

When you create it, it should also create a solution.

Step 4 – Create another empty C# class library project
This will be the test project.  Make sure to stick to a consistent naming convention.  I end my test projects with “.UnitTests” in the name (e.g. BLL.ShoppingCart.UnitTests).  This allows you to specify a wildcard pattern in MSBuild when running tests.  I’ll go into this in more detail below.

Step 5 – Add Rhino.Mocks.DLL reference to test project
Right click on References and click Add Reference.  Locate the RhinoMocks DLL file you extracted in the first step and add it to the project.

Step 6 – Write your test and build solution

When copying my code, please replace the less than/greater than signs with brackets.  The code css styler had a problem with them.

using Rhino.Mocks;

namespace BLL.Cart.UnitTests
{

<TestClass>
public class CartTest
{
private MockRepository _mock;

<TestInitialize>
public void TestSetup()
{

_mock = new MockRepository();
}

<TestMethod>
public void WhenItemAdded_CartQuantityShouldIncrease()
{
//test code
} } }

Step 7 – Create Build Definition and Incorporate Test Assemblies

In Team Explorer, you will go through the regular motions of creating a build definition.  The option that will trigger the tests is on the last option screen where you will indicate your test assembly pattern, as shown in the screenshot inset.

The last thing you will want to make sure is that the Rhino.Mocks DLL you included in the project is added to source control. Otherwise, when MSBuild attempts to build your solution, you will get a reference error and it will not build.

And that’s it.

As always, I’d love to hear your feedback to see if this was helpful or if there is anything I might have missed.

Behavior-Driven Development (BDD) – The What, Why, and How

UPDATE:Incorporating BDD into Visual Studio/TFS? You will want to read this post.

The standard development method they teach you in Software Engineering 101 is

  1. Get your requirements
  2. Come up with a top-bottom architectural design
  3. Code up modules one by one
  4. Test (Unit/System/Regression)
  5. Delivery/Deployment

It’s a great approach and the solution you deliver can be built without compilation errors and work fine… or so you think.  You deliver the solution and all of the sudden, the client points out that there were requirements missed and/or incomplete.  My favorite taught-myself-in-24-hours-developer reaction to this is:

“But… it… compiles… therefore… it works…  it has to!”

With Behavior-Driven Development (BDD), and one of the reasons this approach is favored by QA teams all over the world is this approach ensures and, actually, requires that you work against the user requirements when working on the design.

Let’s say one of the requirements of an HR system being built is that the payroll must be able to use one pay rate when an employee has worked 40 hours or less and a different pay rate for overtime (> 40 hours).

With the top-down approach, you would eventually get down to developing this module, perhaps after the database development is done.  You also wouldn’t really be able to test it until the at least a part of the solution would  build successfully.

The What

With BDD, you tackle it from the requirements side, by writing tests on what the module should and should not do.  One of the great qualities of BDD also is that it stresses on readability.  This means that instead of test method names like TestOvertime(), you get method names like WhenMoreThan40Hours_UserShouldGetPaidOvertime().  That’s the first test.  Second could be something like WhenCalculatingOvertime_UserMustBeEligibleForOvertime().

Now, combine this with the strength of a mocking framework, and you might never go back to top-down.  If you have not heard of this before, mocking frameworks do not highlight your bad code and laugh at you.  In this context, it helps you mock or impersonate your dependencies.

In laymen’s terms, if you are testing a method that calculates hours for an employee and the information is supposed to come from a database, in this case, the database is a dependency.  If you attempt to connect to a database to get your test data and the connection or the query fails for some reason, your test may fail for the wrong reason.  A mock framework let’s you “mock” a call to the database and return test data.

I will get into code details and working with RhinoMocks in a post shortly following this one, but here is what some sample code may look like.

The How

//mock framework - RhinoMocks
var mock = new MockRepository();

//this creates a mock interface of the IDatabase interface
//you don't even need to implement the code
//for this interface in a class to use it here.
var myDatabase = mock.StrictMock<IDatabase>();

var employee = new Employee(myDatabase); //constructor takes in IDatabase object

using(mock.Record())
{
      Expect.Call(myDatabase.
                GetHoursWorkedForEmployeeID("123"))
                .Return(40);
}
using(mock.Playback())
{
     Assert.AreEqual(employee.IsOvertimeEligible,false);
}

The Why

By writing your unit tests first against your requirements, you end up building a system that is unit-test-ready and is very tight with the requirements.

In addition, this is also beneficial when working in a multi-developer team, by having your unit tests written, this ensures that when a developer goes into your module and changes functionality that may work for his module, but breaks yours, it won’t let him check in the solution, but this requires a bit of extra configuration work with MSBuild and Microsoft Team Foundation Server.

Every time you build a new method or make a change to the system, you can run your tests to make sure the new/modified functionality did not break any existing functionality.

In a nutshell, while this may seem like BDD would take longer, you should consider that time you spend on the dreaded back-and-forth with your QA team as they uncover your bugs and easter eggs can be virtually eliminated if you deliver a solution that unit tested itself at compile time or when you checked it into your source control repository.