RSpec is the ultimate bed check
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.

September 1st, 2007 at 10:23 pm
Andy,
That was indeed a sweet little introduction to RSpec. I hope to use it on my next Rails project.
September 5th, 2007 at 1:35 pm
Nice introduction to RSpec. You did a good job of keeping things simple while still informative. I don’t really understand the title though. In fact, when I first saw it I had actually thought it said “bad check”. Regardless, nice work.
September 7th, 2007 at 1:51 pm
Thanks for the compliment, Navjeet!
September 7th, 2007 at 1:54 pm
Chris-
Thanks for your feedback! A bed check is an inspection (at night) to make sure people are where they are supposed to be– RSpec is a framework that enables teams to figure out if they are building what they’re supposed to be building. So bed check is kinda related and it rhymes…kinda.
October 2nd, 2007 at 8:51 am
I think I don’t get BDD. Look at the following JUnit code. How is the RSpec code different, except that it’s slightly more verbose?
I think if you can write low-level unit tests focused on implementation details, you can just as well write high-level tests (focused on “behavior”). Both kinds are important. To me, this “BDD framework” seems to be a unit-testing framework with a few pointless quirks, like “assert” being renamed to “should”.
I seriously don’t get this BDD thing.
October 2nd, 2007 at 8:55 am
Hm, around here, <code></code> tags seem to go wahooni-shaped if they contain multiple lines …
November 6th, 2007 at 11:30 am
[…] Internal DSLs, Groovy style In a previous post, I described a simple framework for creating copasetic specifications– these are written in Groovy and run via a simple Java runner. What’s makes this little framework simple is its specification format– that is, the DSL, which facilitates defining specifications for hip objects. […]
November 13th, 2007 at 11:42 am
[…] I’ll be speaking about BDD, Groovy, and a Martin Fowler inspired subject regarding the future of build languages. My BDD talk will obviously focus on how BDD can drive development more effectively than TDD and I’ll demonstrate some JBehave, RSpec, and a Groovy inspired RSpec knock-off. My Groovy session is a veritable crash course on using Groovy quickly– 101 style, baby. Lastly, the build languages openspaces session is an open discussion regarding Ant style (i.e. XML driven platforms like NAnt and MSBuild) build platforms versus more expressive platforms like Rake, Raven, and Gant, for example. […]