[Rspec-devel] Expecting Rails behaviour

Lachie lachiec at gmail.com
Fri Aug 25 21:16:50 EDT 2006

Did you see the "Ruby, Rails, Test::Rails Cheat Sheet" at
http://nubyonrails.com/articles/read/741 by Geoffrey Grossenbach?

Despite what I think about these cheatsheets in general, this one
presents us with a golden opporunity.

We can use it as a check list of, or discussion pole for the state of
specifying Rails behaviour.

After we've worried/finessed the list below, and/or rspec-on-rails's
capabilities, perhaps we can create a cheatsheet or phrasebook of our
own as a marketing exercise. Although using rspec as a direct T::U
replacement isn't the goal, the translation of assertions into
expectations is quite clear and demonstrates one of rspec's greatest
strengths. Publishing something like a pretty cheatsheet might grab
some people's attention.

I've marked the Test::Unit assertions as TU and the rspec equivalent
as RS. Obviously my translations are not gospel, but I've added them
as a starting point based on my understanding. This also highlights
areas where the translation isn't clear.

Although they mostly cover the expectation api, there's some crossover
with the context api in that rspec-on-rails sets up some Controller
related gear by hooking the context api. And if I have to use "Test"
while talking about RSpec, its because some of the objects we reuse
from rails are actually called TestSomething :).

I've added a bit of background, sorry if its extraneous for you.

Test::Unit Assertions
All these are covered by rspec in the most wonderful of ways

TU assert boolean
RS boolean.should_be true
RS boolean.should_satisfy {|arg| ... }

TU assert_equal expected, actual
RS actual.should_be expected

TU assert_raise *args, &block
TU [deprecated] assert_raises *args, &block
RS lambda { ... }.should_raise *args

TU assert_instance_of klass, object
RS object.should_be_an_instance_of klass

TU assert_nil object
RS object.should_be nil

TU assert_kind_of klass, object
RS object.should_be_kind_of klass

TU assert_respond_to object, method
RS object.should_respond_to :method

TU assert_match pattern, string
RS pattern.should_match string

TU assert_same expected, actual
RS actual.should_be expected

TU assert_operator object1, operator, object2
RS object1.should_satisfy {|o| o <operator> object2}

TU assert_nothing_raised *args
RS lambda { ... }.should_not_raise *args

TU assert_not_same expected, actual
RS actual.should_not_be expected

TU assert_not_equal expected, actual
RS actual.should_not_equal expected

TU assert_not_nil object
RS object.should_not_be nil

TU assert_no_match regexp, string
RS regexp.should_not_match string

TU assert_throws expected_symbol, &proc
RS proc.should_throw expected_symbol

TU assert_nothing_thrown &proc
RS proc.should_not_throw

TU assert_in_delta expected_float, actual_float, delta
RS actual_float.should_be_close expected_float, delta

TU assert_send send_array
RS not sure why this one is necessary, but a direct translation would be:
RS send_array[0].send(*send_array[1..-1]).should_be true

Rails assertions
These assertions hook into rails by
* instantiating an instance of the Controller under test
* instantiating some test-versions of Response, Request etc.
* simulating the request cycle via convenience methods such as get, post etc.

Rspec-on-rails does things pretty much the same way, but tends to
specify behaviour by interrogating the Test-version objects directly,
rather than wrapping them up in asserts. There are plenty of places
where we could monkey-or-officially patch some convenience or
linguistic optimisation into ShouldHelper.

TU assert_response type
RS @response.should_be_success

TU assert_redirected_to options = {}
RS @response.should_be_redirect
RS @response.should_redirect_match something

TU assert_template expected
RS @response.should_render expected

TU assert_recognizes expected_options, path, extras={}
TU assert_generates expected_path, options, defaults={}, extras = {}
TU assert_routing path, options, defaults={}, extras={}

TU assert_tag *opts
RS @response.should_have_tag *opts

TU assert_no_tag *opts
RS @response.should_not_have_tag *opts

TU assert_dom_equal expected, actual
TU assert_dom_not_equal expected, actual

TU assert_valid record
RS record.should_be_valid ** doesn't work!

Test::Rails assertions
Part of ZenTest. It splits so-called "functional" testing into just
Controller and just View.

TU assert_assigned           ivar, value = NOTHING
RS assigns('ivar').should_not_be nil
RS assigns('ivar').should_be nil

TU assert_content_type       type, message = nil
RS @response.header['content-type'].should_equal type

TU assert_flash              key, content
RS @flash.should_include key

I've successfully integrated and used Test::Rails::ViewTestCase with
rspec-on-rails (I can post the code if you're interested). However, I
wasn't specifying HTML views, so I'm not sure what the best way to
handle these assertions is. Has anyone looked into using Hpricot?

TU assert_image              src
TU assert_error_on           field, type
TU assert_field              form_action, type, model, column, value = nil
TU assert_input              form_action, type, name, value = nil
TU assert_label              form_action, name, include_f = true
TU assert_links_to           href, content = nil
TU * deny_links_to
TU assert_multipart_form     form_action
TU assert_post_form          form_action
TU assert_select             form_action, model, column, options
TU assert_submit             form_action, value
TU assert_tag_in_form        form_action, options
TU * deny

Again, no-brainers for rspec!

TU assert_empty              obj
RS obj.should_be_empty
TU * deny_empty
RS obj.should_not_be_empty

TU assert_includes           obj, item, message = nil
RS obj.should_include item
TU * deny_includes
RS obj.should_not_include item


More information about the Rspec-devel mailing list