I have moved my active blog over to tumblr. I've maintained this blog for reference but will be posting to http://www.robustsoftware.co.uk instead. I've pointed my Feedburner feed to tumblr so if you're subscribed already you should already have switched with me.

Beauty of RSpec

I've only been using RSpec in anger for a short period of time but I'm in love with it already. It's support for BDD is fantastic. I'm now looking forward to the proper release of IronRuby even more than I was before.

I've only written a single class so far, but I'm delighted with the way the tests look so I thought I'd share them:


require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

describe "setting a person's password" do

given do
@person = Person.new
end

because do
@person.set_password "testing"
end

it "sets their password salt" do
@person.password_salt.should_not be_nil
end

it "sets their password hash" do
@person.password_hash.should_not be_nil
end

end

context "when someone has been saved" do

given do
@person = Person.new(:name => "tester")
@person.set_password "testing"
@person.save
end

describe "providing their credentials" do

because do
@retrieved = Person.with_credentials(:name => "tester", :password => "testing")
end

it "retrieves the expected person" do
@retrieved.should == @person
end

end

describe "providing the wrong password" do

it_raises "an error informing the password is incorrect", "Incorrect password" do
Person.with_credentials(:name => "tester", :password => "wrong")
end

end

end

describe "providing credentials for someone who does not exist" do

it_raises "an error informing the name is unknown", "Unknown name" do
Person.with_credentials(:name => "tester", :password => "unsaved")
end

end

The output when you run the tests looks like:

~$ rake spec:doc
(in /home/garry/code/rails/tinytweet)

setting a person's password
- sets their password salt
- sets their password hash

when someone has been saved providing their credentials
- retrieves the expected person

when someone has been saved providing the wrong password
- raises an error informing the password is incorrect

providing credentials for someone who does not exist
- raises an error informing the name is unknown

For those of you familiar with RSpec, you may notice that I'm not using the standard syntax. "given" and "because" are just aliases for "before". I've done this because I like the given/when/then style of tests but as "when" is a Ruby keyword and "it" helps you name the assertions properly for the docs it has become given/because/it.

I've also added an extra method "it_raises" as I found the way of testing that an error is raised rather clunky so I hid the nuts and bolts of it within my spec_helper.rb:

def it_raises(description, error_message)
it "raises " + description do
lambda { yield }.should raise_error error_message
end
end

No doubt I'll have more to share as my journey with Rails and RSpec continues.