Speculating with Shoulda

Shoulda used RSpec


Shoulda’s users have long enjoyed the brevity and simple, declarative nature of macros. These test-generating methods cut the most common ActiveRecord and ActionPack tests down to one beautiful, readable line. However, it doesn’t seem fair in this time of unity to leave our RSpec brothers and sisters out in the cold. If you like RSpec and Shoulda, but would just as soon never use the word Test::Unit::TestCase again, you have some good news in store.

Shoulda’s ActiveRecord macros have been rewritten to use RSpec-like matcher classes under the hood. That means that, providing you’re using at least version 1.1.12 of RSpec, you can write model specs like this:

describe User do
  it { should belong_to(:account) }
  it { should have_many(:posts) }
  it { should validate_presence_of(:email) }
  it { should allow_value("test@example.com").for(:email) }
  it { should_not allow_value("test").for(:email) }

You can see more examples in the Shoulda rdoc. We’ve also added a dash of detection so that RSpec users can just require ‘shoulda’ and be on their way - the ActiveRecord matchers will be mixed into your model examples automatically.

The ActionPack macros haven’t been converted yet, but that process is already under way, so stay tuned for those. By Shoulda 3.0, we plan to have every macro in Shoulda to RSpec users.

For all your loyal Test::Unit users out there, you can keep using the same syntax you’ve always used:

class UserTest < ActiveRecord::TestCase
  should_belong_to :account
  should_have_many :posts
  should_validate_presence_of :email
  should_allow_values_for :email, "test@example.com"
  should_not_allow_values_for :email, "test"

Whether you like to TDD, BDD, test, or spec, Shoulda macros are available for a framework near you!

Thanks go out to David Chelimsky for helping to make integration with RSpec a possibility.

Update: if you’re having issues with undefined methods when using Shoulda with RSpec via config.gem, try updating to Shoulda 2.9.1.

Consistent Naming

Those of you familiar with Shoulda may have noticed the new names in the examples above. If you’ve ever had to dive into the Shoulda documentation to figure out if the method you were looking for was shouldrequireattributes or shouldrequirepresenceof or shouldneedtohave_a, the latest version will bring some peace to your mind. Shoulda macros that directly corresponded to an ActiveRecord validation macro have been renamed to follow the fine example set by Rails:

# Before:
should_require_attributes :name
should_require_unique_attributes :email
should_only_allow_numeric_values_for :age
should_require_acceptance_of :terms_of_service

# After:
should_validate_presence_of :name
should_validate_uniqueness_of :email
should_validate_numericality_of :age
should_validate_acceptance_of :terms_of_service

We’ve also renamed should_protect_attributes and added a new macro for consistency:

# Before:
should_protect_attributes :password

# After:
should_allow_mass_assignment_of :name, :email
should_not_allow_mass_assignment_of :password

The old names still work for now, but you’ll see deprecation warnings in your tests.

Pair with one of our expert developers to level up your skills with Coaching by thoughtbot. Save time learning best practices and techniques for reducing technical debt in Ember, Ruby, Haskell, and Go in 1-on-1 sessions tailored to your goals.