Behavior Driven Development

Some months ago I visited Aslak Hellesøys’ RSpec presentation at RubyEnRails 2007. I was really intrigued by some of the concepts introduced by RSpec.

After checking out the way testing/TDD works in Grails I just had to see if my initial interest in RSpec would stand ground.

Just to recapitulate on what RSpec is:

RSpec is a framework which provides programmers with a Domain Specific Language to describe the behavior of Ruby code with readable, executable examples that guide you in the design process and serve well as both documentation and tests.

So RSpec gives a developer the means to write tests in a form that matches specification of functional requirements dictated by the customer. They call it behavior driven design.

Conceptually I think this is a good thing. Quite often customers don’t actually know what is being tested in their project. Just look at one of the basic methods most often used in testing: assertNotNull. How does a customer know what this is supposed to test? The most obvious answer to this is: documentation/comments… which to be frankly isn’t something most developers excel in.

Now, what does it look like… and how do you use it?

Installing rspec and its’ Rails plugin is a breeze:

[code]
bash> sudo gem install rspec
bash> cd {my_rails_project}
bash> ruby script/plugin install svn://rubyforge.org/var/svn/rspec/tags/CURRENT/rspec
bash> ruby script/plugin install svn://rubyforge.org/var/svn/rspec/tags/CURRENT/rspec_on_rails
[/code]

After installing the plugins in your Rails project a couple of new rake tasks are available (prefixed with spec:) to create run tests for your models/views/controllers/helpers etc.

RSpec also install some generators: rspec, rspec_controller, rspec_model, rspec_scaffold. These generators are similar to the default Rails counterparts but generate corresponding RSpec tests as opposed to unittests.

Let’s get started.

Say we have a really simple specification for a model: “if a new article is created its’ description field should contain ‘no description entered’”.

So, let’s start with creating a simple model:

[code]
bash>./script/generate rspec_model Article title:string, description:string
[/code]

This will give us, next to the expected model file and migration, a file called article_spec.rb in the spec directory:

[ruby]
require File.dirname(__FILE__) + ‘/../spec_helper’

describe Article do
before(:each) do
@article = Article.new
end

it “should be valid” do
@article.should be_valid
end
end
[/ruby]

Which we can run immediately:

[code]
bash>rake spec
(in /Users/peter/Development/rails/brs)
.

Finished in 0.045879 seconds
[/code]

And, we can also create a simple overview of the specifications which we test:

[code]
1 example, 0 failures
bash>rake spec:doc
(in /Users/peter/Development/rails/brs)

Article
- should be valid
[/code]

Cool, now let’s add our specification:

[ruby]
it “the description attribute should contain ‘no description entered’” do
@article.should == “no description entered”
end
[/ruby]

Running the tests results in an error now:

[code]
'Article the description attribute should contain 'no description entered'' FAILED
expected: "no description entered",
got: nil (using ==)
[/code]

Setting the default value for the description attribute of Article like this:

[ruby]
class Article < ActiveRecord::Base
def initialize(attributes = {})
super(attributes)
write_attribute(:description, "no description entered")
end
end
[/ruby]

Results in a successful test. And running spec:doc now tells me I have a test for this specification:

[code]
bash>rake spec:doc
(in /Users/peter/Development/rails/brs)

Article
- should be valid
- the description attribute should contain ‘no description entered’
[/code]

Conclusion
Although this is a really basic example (and there is much more the RSpec) I think I got the point.
I really like the "behavior driven" way of thinking; it provides clear handles for writing tests and creates useful overviews of what is actually tested.

This entry was posted in bdd, rails, rspec, ruby. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>