Wednesday, December 10, 2008

Behavior Driven Development (BDD) in F# with SpecUnit .NET

BDD Overview:

Behavior Driven Development (BDD) is a process that evolved from Test Driven Development (TDD).  The differences are subtle and primarily focus on removing communication related confusion (Dan North-the founder of BDD-provides a nice introduction here). describes BDD as a convergence of TDD and Domain-Driven Design (DDD) - (A good introduction to DDD can be found on Hanselminutes show #140 with Rob Conery).  One of the foundations of DDD is the concept of removing complexity by creating a common language to help bridge the gap between business and technology .  This common language is known as the ubiquitous language. 

The first thing that BDD does to help accomplish the goal of a ubiquitous language is remove the central focus on "tests".  Generally, when the word "Test" is mentioned to a business minded person, they will immediately think about a quality assurance process that is situated near the end of a project plan.  By changing the termonology from "Test" to "Specification", the focus changes to something done near the beginning of the project plan that defines and drives the development of the solution.  This small focal shift can make a big difference in how the project is driven.

BDD also has advantages for developers.  When specifications are documented in code, that code is more likely to accomplish the business goals, be easier to understand, and be much more maintainable over the life of the solution.  In addition, the specifications written to drive the development can then be used to prove that the final product meets all of the business requirements.

There are many additional benefits to BDD.  For additional information, check out

BDD in F#:

After reading Starting with BDD vs. TDD, I decided to checkout SpecUnit .NET.  I pulled down the sample application (i.e. Banking) and did a quick and dirty port to F#. 


namespace BankingFSharp.Specs
open NUnit.Framework
open SpecUnit
open BankingFSharp

[<Concern("funds transfer")>]
type behaves_like_context_with_from_account_and_to_account() = 
    inherit ContextSpecification()
    val mutable fromAccount : Account
    val mutable toAccount : Account
    override this.Context () = 
        this.fromAccount <- new Account(1m) 
        this.toAccount <- new Account(1m) 
        ignore None

[<Concern("funds transfer")>]
type when_transferring_between_two_accounts() = 
    inherit behaves_like_context_with_from_account_and_to_account()
    override this.Because () = 
        this.fromAccount.Transfer(1m, this.toAccount) |> ignore
    member this.should_debit_the_from_account_by_the_amount_transferred () =  
        this.fromAccount.Balance.ShouldEqual(0m) |> ignore
    member this.should_credit_the_to_account_by_the_amount_transferred () =  
        this.toAccount.Balance.ShouldEqual(2m) |> ignore

namespace BankingFSharp
open System

type Account = class
  val mutable balance: decimal;
  new (balance) = {balance = balance}
  member this.Balance
      with get() = this.balance and set(v) = this.balance <- v
  member this.Transfer (amount,toAccount:Account) = 
      if amount > this.balance then
           let errorMessage = String.Format("Cannot transfer ${0}. The available balance is ${1}.", amount, this.balance)
           failwith errorMessage
          this.Balance <- this.balance - amount
          toAccount.Balance <- toAccount.Balance + amount


When NUnit was opened, it was exciting to see how much of the story was now being conveyed through the tests. While this is not completely ubiquitous, the output (i.e. " when transferring between two accounts" "should create the to account by the account transferred") is pretty close to what one would see in a requirements document.



BDD is a positive step toward closing the gap between business and technology.  Tools such as SpecUnit .NET make this process easier and it was refreshing to see out of the box support for F#.  As more developers start to see the benefits of TDD and BDD, we will see the infamous divide between business and technology finally start to close.

1 comment: