Behavior Driven Development (or BDD) is a slight modification of Test Driven Development (or TDD) in that BDD stresses the term “should” over “test”– and as it turns out, by focusing on behavior through a focus on should, you can more easily specify behavior early. TDD, as you may know, also stresses verification early, but because it focuses on the term “test” there are challenges, such as getting developers to think in terms of testing first. Don’t get me wrong, there are a number of passionate TDD gun slingers throughout our industry who have readily adopted a strict notion of testing up front; however, they are unfortunately a minority.

Interestingly, BDD has spawned a number of frameworks that aim to make this up front specification based verification easy to create. One particular framework is Ruby’s RSpec, which has put to use an innovative DSL for specifying behavior quite straight forward. For example, imagine a customer has tasked you with creating a zip code verification service. This service is ultimately intended to permit valid zip code and deny invalid ones. Working with your customer, you both come up with a series of requirements regarding this service:

  • The zip code validation service should accept 5 digits in a row, like 22101
  • It should accept 5 digits followed by 4 digits (with a hyphen separator), like 22101-5051
  • It should deny any characters found in a zip code, like 221o1
  • It should deny any pattern that has fewer than 5 digits in the first phrase, like 2210
  • It should deny any pattern that has fewer than 4 digits in the second phrase, like 22101-5

Note that these requirements don’t specify how this verification will be carried out. They are written from a user’s point of view– they ultimately don’t care how you implement it, so long as it works, right? The nice thing about the list above is that using RSpec, I can essentially copy and paste them into code. Watch:

First, I need to create a file and use RSpec’s describe clause, which declares what this behavior is intended to model.

require 'zipcode_validator'

describe ZipCodeValidator do

end 

Next, using the it phrase, I can literally paste in my requirements and wrap them with a do and an end as shown below.

it "should accept 5 digits in a row, like 22101" do
end

it "should accept 5 digits followed by 4 digits, like 22101-5051" do
end

it "should deny any characters in a zip code, like 221o1" do
end 

it "should deny any pattern that has fewer than 5 digits in the 
 first phrase, like 2210" do
end

it "should deny any pattern that has fewer than 4 digits in the  
 second phrase, like 22101-5" do
end

With my behaviors defined, I can now create a context– in it, I define a reference to my, as yet to be defined, ZipCodeValidator service object. The before(:each) method means that a new instance will be created for each behavior.

before(:each) do
 @validator = ZipCodeValidator.new
end

Next, I can implement the first behavior and ensure that the service permits the valid zip code. Note how RSpec allows me to use the should method on my object.

it "should accept 5 digits in a row, like 22101" do
 @validator.validate("22101").should == true
end

If I run my behavior class now, it’ll fail as I haven’t even coded any implementation yet. That’s ok though as I’ve been focused on the specification of the object. I can show my customer the behaviors if they speak geek (or Ruby) and engage in some collaborative verification to ensure that I’m going down their desired route as well. Once everyone is on the same page, I can then turn to implementing the ZipCodeValidator service.

class ZipCodeValidator

  def validate(zipcode)
    if  (/^d{5}([-]d{4})?$/ =~ zipcode) == 0 then return true
    else return false
    end
  end

end

With the ZipCodeValidator object coded, I can code the other behaviors to ensure the negative path works, that is, that the object “should deny any pattern that has fewer than 5 digits in the first phrase, like 2210″ for example.

it "should deny any pattern that has fewer than 5 digits in 
 the first phrase, like 2210" do
  @validator.validate("2210").should == false
end

Putting it all together yields a behavior class with 5 behavior methods corresponding to the requirements from earlier. Plus, this exercise also resulted in a functional ZipCodeValidator object.

require 'zipcode_validator'

describe ZipCodeValidator do

  before(:each) do
    @validator = ZipCodeValidator.new
  end

  it "should accept 5 digits in a row, like 22101" do
    @validator.validate("22101").should == true
  end

  it "should accept 5 digits followed by 4 digits, like 22101-5051" do
    @validator.validate("22101-5051").should == true
  end

  it "should deny any characters in a zip code, like 221o1" do
    @validator.validate("221o1").should == false
  end 

  it "should deny any pattern that has fewer than 5 digits in the 
   first phrase, like 2210" do
    @validator.validate("2210").should == false
  end

  it "should deny any pattern that has fewer than 4 digits in the 
   second phrase, like 22101-5" do
    @validator.validate("22101-5").should == false
  end

end 

Running the behavior shows that things work as planned!

aglover$ spec zipcode_spec.rb
.....

Finished in 0.007737 seconds

5 examples, 0 failures

RSpec’s intuitive DSL for defining behavior makes BDD a breeze; plus, the elegance of defining the specification in concert with a behavior class drives development in a rapid manner that builds confidence quickly, while also facilitating collaboration with customers and domain experts.