In short, according to Dave Astels (rSpec core developer), if you are doing test driven development (TDD) properly you are already doing behavior driven development (BDD).
BDD takes the concept of test first and puts it in a behavior specific domain. Why would someone use a BDD framework over a TDD framework? BDD frameworks like rSpec don't do anything that other unit testing frameworks can't do, they just put it in terms of behavior specification instead of generic assertions. To help the point get across I present this analogy:
There is no reason a unit test framework cannot be used to specify behavior of a piece of code, but then again there is a reason why C might not be the best choice of language to implement an object oriented design.
An example is worth a thousand descriptions: say we want a really cool car, one that can top out around 200 mph and run a quarter mile in 10 seconds (give or take a second.)
Using
Test::Unit
we can specify the behavior thusly:require 'test/unit'
require 'cool_car'
class CoolCarTest < Test::Unit::TestCase
def setup
@car = CoolCar.new
end
def test_quickness
@car.accellerate until @car.distance >= 0.25
assert_in_delta 10, @car.time_driven, 1.1
end
def test_speed
last_speed = -1
until @car.speed == last_speed
last_speed = @car.speed
@car.accellerate
end
assert_in_delta 200, @car.speed, 1.1
end
end
not bad, we specified the behavior of a car that will do what we want, nothing more, nothing less. lets try it again but in rSpec:
require 'cool_car'
describe CoolCar do
before(:each) do
@car = CoolCar.new
end
it "should run a quarter mile in 10 +/- 1.1 seconds" do
@car.accellerate until @car.distance >= 0.25
@car.time_driven.should be_close(10, 1.1)
end
it "should have a top speed of 180 mph or better" do
last_speed = -1
until @car.speed == last_speed
last_speed = @car.speed
@car.accellerate
end
@car.speed.should be_close(200, 1.1)
end
end
Ahh much nicer.
here is
cool_car.rb
:class CoolCar
attr_reader :distance, :speed, :time_driven
def initialize
@distance = 0.0 # in miles
@speed = 0.0 # in mph
@time_driven = 0.0 # in seconds
end
# accellerate for one second
def accellerate
@time_driven += 1
@speed += 1 if @speed < 200
@distance += 0.025
end
end
The laws of physics don't really apply, but the spec does! (send me a class for a CoolCar that is a little more realistic and i'll update this, you have a spec).
BDD is more than a cute way to write tests in a more natural language, it's a way to specify semantically and syntactically behavior (and only behavior) of of software. From what is demonstrated above we can clearly see that BDD and rSpec are must see stops along the path of agile enlightenment.
For a great intro to BDD and rSpec check out Dave Astels' talk: