Shoulda, RSpec, shoulda-matchers and models validations unit testing

I was trying out RSpec framework in a project and got stopped doing the unit test of a model. In particular, doing the test for the associations and the ActiveRecord validations.

I started writing the validations but my tests didn’t look DRY at all. Before refactoring the tests checked out and look for other people solutions.

I found out shoulda-matchers and Shoulda (which is I didn’t get it wrong is another testing framework). Actually I found another one, remarkable, but it look it doesn’t work with Rails 3.

Does anyone have any advice, comments, suggestion on this matter?

Right now I continue on using RSpec and shoulda-matchers. The last one mainly for testing the validations and associations of the models.

Any advice and/or help will be appreciated.

Thanks in advance.

You can start reading at section 6.2, and see how the Rails 3 Tutorial tests validations:

http://ruby.railstutorial.org/chapters/modeling-and-viewing-users-one#sec:user_model

Already got something like that. The main difference, is that I’m using factories.

The problem with my test, which almost follow those examples, is that I’m repeating myself each time I want to validate the same (uniqueness, length, etc).

One option is to create methods for each type of validation and that way the test will be DRY. Instead of that I was looking if there is a gem that provide me with those (keep them updated, etc).

At that point is when I found shoulda-matchers.

Otherwise this is an example of how the test looks

class User < ActiveRecord::Base

validates :first_name,

:presence => true,

:length => { :maximum => 32 }

validates :last_name,

:presence => true,

:length => { :maximum => 32 }

end

According to the examples your tests for those fields should been:

describe User do

before(:each) do

@attr = { :first_name => “Foo”, :last_name => “Bar” }

end

it “should require a first name” do

no_email_user = User.new(@attr.merge(:first_name => “”))

no_email_user.should_not be_valid

end

it “should require a last name” do

no_email_user = User.new(@attr.merge(:last_name => “”))

no_email_user.should_not be_valid

end

it “should reject first names that are too long” do

long_first_name = “a” * 33

long_first_name_user = User.new(@attr.merge(:first_name => long_first_name))

long_first_name_user.should_not be_valid

end

it “should reject last names that are too long” do

long_last_name = “a” * 33

long_last_name_user = User.new(@attr.merge(:last_name => long_last_name))

long_last_name_user.should_not be_valid

end

end