---
title: Shoulda 2.0
teaser:
tags: news,web,ruby,testing,shoulda
author: Dan Croak
published_on: 2008-09-30
---

Lots of shoulda news to report. The 2.0.x gem has been released, which includes
bug fixes, new features, and deprecations.

## Rails 2.1+ install

The gem is being hosted at
[github.com/thoughtbot/shoulda](http://github.com/thoughtbot/shoulda).

Specify the gem dependency in your config/environment.rb file:

```ruby
Rails::Initializer.run do |config|
  config.gem 'thoughtbot-shoulda', :lib => 'shoulda/rails', :source => "http://gems.github.com"
end
```

Then:

```sh
rake gems:install
rake gems:unpack
```

## Now 100% gem

![gems](http://images.thoughtbot.com/ui/2008-9-30-carmen_lucia_ruby.jpg)

Why gems?

* Ruby comes with a packaging system. No need for another, especially with the
  gem support in Rails 2.1.
* It's nice to scan the vendor/gems listing and see version numbers.
* [github](http://gems.github.com) has excellent gem support.
* In shoulda's case, it's a project that can be used in and out of Rails. It's a
  pain to have both a plugin and a gem.

Ryan McGeary and Josh Nichols did the bulk of this conversion and related
refactoring. They deserve extra acclaim because they've made it easier for
everyone to contribute to shoulda.

## Improvements to current macros

`should_assign_to` now takes an :equals option. This is now the preferred way to
use `should_assign_to` for edit, show, update, and destroy actions because it is
a better test when you explicitly compare `assigns(:user)` to an expected
object.

```ruby
should_assign_to :user, :equals => "@user"
```

`should_assign_to` also now takes a `:class` option. This is especially good for
new actions.

```ruby
should_assign_to :user, :class => User
```

`should_have_one` now supports the :dependent option.

```ruby
should_have_one :address, :dependent => :destroy
```

`ActiveRecord::Errors.default_error_messages` is used instead of home-brewed
regexes for all Active Record macros.

## New Macros

`should_change` creates a test asserting a change between the return value of an
expression that is run before and after the current setup block is run. This is
similar to Active Support's `assert_difference` assertion, but supports more
than just numeric values.

```ruby
context "Creating a post"
  setup { Post.create }
  should_change "Post.count", :by => 1
end

# :from and :to examples
should_change "Post.count", :from => 0, :to => 1
should_change "@post.title", :from => "old", :to => "new"
```

`should_not_change` creates a test asserting no change between the return value
of an expression that is run before and after the current setup block is run.

```ruby
context "Updating a post"
  setup { @post.update_attributes(:title => "new") }
  should_not_change "Post.count"
end
```

`should_filter_params` creates a test asserting that `filter_parameter_logging`
is set for the specified keys `should_filter_params :password, :ssn`

`should_render_with_layout` creates a test asserting that the controller
rendered with the given layout.

```ruby
should_render_with_layout # defaults to application
should_render_with_layout 'special'
should_render_without_layout
```

`should_route` creates a routing test. It tries to use the given HTTP method on
the given path, and asserts that it routes to the given options.

```ruby
should_route :get, "/posts", :controller => :posts, :action => :index
should_route :delete, "/posts/1", :action => :destroy, :id => 1
should_route :get, "/users/1/posts/1",
  :action => :show, :id => 1, :user_id => 1
```

`should_respond_with_content_type` creates a test asserting that the response
content type was `content_type`.

```ruby
should_respond_with_content_type 'application/rss+xml'
should_respond_with_content_type :rss
should_respond_with_content_type /rss/
```

`should_return_from_session` creates a test asserting that a value returned from
the session is correct. The given string is evaled to produce the resulting
redirect path.  All of the instance variables set by the controller are
available to the evaled string.

```ruby
should_return_from_session :user_id, "@user.id"
```

## Before statements

Before statements are should statements that run before the current context's
setup. These are especially useful when setting expectations.

```ruby
class UserControllerTest < Test::Unit::TestCase
  context "the index action" do
    setup do
      @users = [Factory(:user)]
      User.stubs(:find).returns(@users)
    end

    context "on GET" do
      setup { get :index }

      should_respond_with :success

      # runs before "get :index"
      before_should "find all users" do
        User.expects(:find).with(:all).returns(@users)
      end
    end
  end
end
```

## Automatically load custom macros

Writing custom macros is a common practice for [The Modern Shoulda
Developer](http://images.thoughtbot.com/ui/2008-9-30-suspenders.png). For
example,
[should\_have\_attached\_file](https://thoughtbot.com/blog/testing-paperclip-with-shoulda)
used to be a handy custom macro to have around when you're using Paperclip.

There were a few problems with that, however. Where should that macro go?
`RAILS_ROOT/test/test_helper.rb`? Why do we have the same macro in multiple apps
for the same plugin?

Enter the new `shoulda_macros` directory. Shoulda will automatically load custom
macros she finds in:

    RAILS_ROOT/test/shoulda_macros
    RAILS_ROOT/vendor/gems/#{gem_name}/shoulda_macros
    RAILS_ROOT/vendor/plugins/#{plugin_name}/shoulda_macros

Now, every Paperclip user can use the latest
[should\_have\_attached\_file](http://github.com/thoughtbot/paperclip/tree/master/shoulda_macros/paperclip.rb)
because it is where it belongs.

## `should_be_restful` is being deprecated

`should_be_restful` will be removed in a future release. It is currently in a
grace period where you'll see a warning during your test runs. It will be added
to the new [woulda](http://github.com/seanhussey/woulda) gem if you care to keep
using it. Its problems:

* It dissuades the programmer from good <abbr title="Test Driven
  Development">TDD</abbr> practice.  It's working at too high level of
  abstraction and encourages the programmer to take too many big steps.
* It is an attempt to be like Rails scaffolding, which is a good way to learn
  REST, but the syntax is so cryptic it doesn't accomplish that goal.
* It's near impossible to find the line in your test file that is actually
  failing or erroring.
* You have no idea how many tests it generates or how they're implemented, which
  lulls the programmer into a false sense of security.

## Removed

* The `load_all_fixtures` (use `fixtures :all` instead)
* The `shoulda.conf` and color support (use the
  [redgreen](http://errtheblog.com/posts/-colored-tests) gem instead)

## Credit

[Ryan McGeary](http://github.com/rmm5t), [Matt
Jankowski](http://github.com/mjankowski), [Mike Boone](http://github.com/boone),
[Tammer Saleh](http://github.com/tsaleh), [Josh
Nichols](http://github.com/technicalpickles), [Joe
Ferris](http://github.com/jferris), [Keith Morrison](http://github.com/infused),
[Dan Croak](http://github.com/croaky).
