Web Developer's Virtual Library: Encyclopedia of Web Design Tutorials, Articles and Discussions


Java/Open Source Daily

jobs.webdeveloper.com

e-commerce
Partner With Us















Developer Channel
FlashKit.com
JavaScript.com
JavaScriptSource
Developer Jobs
ScriptSearch
StreamingMediaWorld
Web Developer's Journal
Web Developer's Virtual Library
WebDeveloper.com
Webreference
Web Hosts
XMLfiles.com

internet.com
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers


Apply Behavior Driven Development to Ruby on Rails with Rspec

Bookmark and Share

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.

saurabh@home:/media/S3A6128D005/Users/ongc/eim$ script/plugin install git://github.com/dchelimsky/rspec-rails.git
Initialized empty Git repository in /media/S3A6128D005/Users/ongc/eim/vendor/plugins/rspec-rails/.git/
remote: Counting objects: 218, done.
remote: Compressing objects: 100% (176/176), done.
remote: Total 218 (delta 15), reused 129 (delta 3)
Receiving objects: 100% (218/218), 87.67 KiB | 93 KiB/s, done.
Resolving deltas: 100% (15/15), done.
From git://github.com/dchelimsky/rspec-rails
 * branch            HEAD       -> FETCH_HEAD

After installation, I am ready to create the directories required for spec with the following command:

saurabh@home:/media/S3A6128D005/Users/ongc/eim$ ruby script/generate rspec
Configuring rspec and rspec-rails gems in config/environments/test.rb ...

      exists  lib/tasks
      create  lib/tasks/rspec.rake
      create  script/autospec
      create  script/spec
      create  spec
      create  spec/rcov.opts
      create  spec/spec.opts
      create  spec/spec_helper.rb

Applying BDD with RSpec

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.

saurabh@home:/media/S3A6128D005/Users/ongc/eim$ script/generate rspec_model Hobby
      exists  app/models/
      create  spec/models/
      create  spec/fixtures/
      create  app/models/hobby.rb
      create  spec/models/hobby_spec.rb
      create  spec/fixtures/hobbies.yml
      exists  db/migrate
      create  db/migrate/20100112073803_create_hobbies.rb

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.



Up to => Home / Authoring / Tutorials / Ruby on Rails