Apply Behavior Driven Development to Ruby on Rails with Rspec
by Saurabh Bhatia
February 04, 2010
Applying the Behavior Driven Development (BDD) methodology to your Rails development takes you beyond traditional Test Driven Development. Learn how to do it with the Ruby-based BDD framework RSpec.
Introduction
Applying the Behavior Driven Development (BDD) methodology with a Ruby-based BDD framework allows developers to write system requirements in a Ruby format first and then write Ruby code for the particular features of those requirements. Because the Ruby format is similar to plain English, business analysts and the people gathering the requirements can participate in the development process.
BDD mandates that developers write tests for each step of the process, which leads to cleaner code. The BDD process begins with the development team creating a scenario, for which they describe each feature. The initial scenario inevitably fails. The team subsequently defines each step (iterative test) and writes the application code for each feature. They also refactor the code when the scenario passes each step.
A few different Ruby-based BDD frameworks are available. RSpec, Cucumber, and Shoulda are the most popular. Let's see how RSpec works by using the use case of an employee information manager.
Installing RSpec and Creating Required Directories
The installation of RSpec is pretty straightforward. I just use the gem install command on the command line.
saurabh@home:~$ sudo gem install rspec
[sudo] password for saurabh:
**************************************************
Thank you for installing rspec-1.2.9
Please be sure to read History.rdoc and Upgrade.rdoc
for useful information about this release.
**************************************************
Successfully installed rspec-1.2.9
1 gem installed
Installing ri documentation for rspec-1.2.9...
Installing RDoc documentation for rspec-1.2.9...
Next, I make RSpec locally available to my Rails application and add it as a plugin to my Rails. When I run this installation, the RSpec-Rails plugin will be installed within the Vendor directory of the Rails application.
Now, let's take on the scenario of collecting employee information and define it using RSpec according to the BDD process. While collecting employee details, we will also collect information regarding their interests and hobbies. So, here is how we present the scenario:
User goes to the hobby page.
User enters a list of sports he/she likes.
The user cannot leave any box blank.
Now that we have a description of the scenario, we can start writing the model specs. Before that, however, we need to create the skeleton code for the model spec.
BDD helps to create context for the scenarios. Here's how our feature specification for hobbies looks like.
context "A user " do
setup do
@hobby = Hobby.new
end
specify "should be invalid without all boxes filled"
@hobby.should_not_be_valid
@hobby.sports = "sportname"
@hobby.should_be_valid
end
end
Now, we need to write the code for this feature in order to make it pass. In order to do so, we require a hobby model and table. We add the tables using migrations.
class CreateHobbies < ActiveRecord::Migration
def self.up
create_table :hobbies do |t|
t.column :sports, :string
t.timestamps
end
end
def self.down
drop_table :hobbies
end
end
When we look at our specs, we see that the sports field is a mandatory. Hence, we need to add a validation in the Hobby Model.
class Hobby < ActiveRecord::Base
validates_presence_of :sports
end
In order to run the tests, we need to create the test database and set up the test environment correctly. After that, we can run the spec we just defined.
saurabh@home:/media/S3A6128D005/Users/ongc/eim/spec/models$ spec hobby_spec.rb
F
1)
ActiveRecord::RecordInvalid in 'Hobby should create a new instance given valid attributes'
Validation failed: Sports can't be blank
./hobby_spec.rb:11:
Finished in 0.03787 seconds
1 example, 1 failure
The test fails because the Validation says sports can't be blank. Voila! We've done it; the validations are running. Let's add some data and pass the values to the test. We will run them again when the data is specified and see if they pass or not.
Data is passed in RSpec through the spec_helper. In this case, the test data needs to be a value for sports. So, we use spec_helper to pass the value of our sport through to the spec under the valid_attribute specification.
require 'spec_helper'
describe Hobby do
before(:each) do
@valid_attributes = {
:sports => 'soccer'
}
end
it "should create a new instance given valid attributes" do
Hobby.create!(@valid_attributes)
end
end
Now, we run the spec tests again and check.
saurabh@home:/media/S3A6128D005/Users/ongc/eim/spec/models$ spec hobby_spec.rb
.
Finished in 0.189719 seconds
1 example, 0 failures
The test passed! We have just finished writing a feature using RSpec.
Conclusion
Behavior Driven Development is an effective methodology that reduces the time required for requirements gathering, because business analysts write their specs in the rspec format and developers can write code to meet that specification. It also introduces better discipline and control over tests.
About the Author
Saurabh Bhatia has been working with Rails since early 2006 and has a startup company, Safew Labs, that offers Rails consulting. He likes to write clean code, read and write.