Some functional testing gotchas in Ruby on Rails

I’ve been writing lots of functional tests lately and came across several unexpected gotchas. Seeing as how forgetful I am recently, I’ll jot them down here (and hopefully benefit anyone else who comes across the same problems).

Testing flash.now

Testing the contents of the flash.now, somewhat surprisingly, can’t be done with code like this:

assert_equal 'Unable to activate your account.',
  flash.now[:error]

flash.now[:error] would be nil, in your functional test, and a quick lookup on Google brought me to HowToTestFlash.Now on the Rails wiki. Apparently, Rails renders the flash in the view and then proceeds to clear the contents of flash.now (so it isn’t accessible in your functional test). So, you’d have to test the contents of the rendered page, instead of testing the flash itself:

assert_tag :tag => 'div',
               :attributes => { :class => 'flash error' },
               :content => 'Unable to activate your account.'

Asserting cookies

This one’s particularly annoying - trying to assert that cookies are set by your controllers. Unlike what was written in the Rails manual on testing (granted, it’s rather well-known that the manuals are somewhat outdated), you cannot retrieve cookies using a Symbol as an index into the cookies hash in your functional tests.

cookies[:auth_token] = {
  :value => session[:user].remember_token,
  :expires => session[:user].remember_token_expires_at
}

assert cookies[:auth_token]  # nil
assert cookies['auth_token']  # This works.

Thanks to Herry for pointing this out - it saved me an exercise in frustration.

Yet another cookie testing gotcha is testing for the deletion of cookies (example use case: deleting a users cookie after he logs out). So you may do this in your controller:

cookies.delete :auth_token

And expect this to pass in your test:

assert_nil cookies['auth_token']

But nope, instead of setting the cookie to nil, the cookie is actually emptied.

assert cookies['auth_token'].empty?  # This works.

I just used wrote my own custom assertion (there is an assert_cookie plugin around but I didn’t think this justified adding another plugin to the application, not just yet):

def assert_no_cookie(cookie_name)
  cookies[cookie_name].nil?
    || cookies[cookie_name].empty?
end

Update: as it turns out, assert_no_cookie and assert_cookie_equals exist as custom assertions in ActionPack (source), but have been deprecated in favor of the cookies collection. Still, looking up the cookies collection with a Symbol but having it return nil is unexpected behavior considering the inline documentation says it should work.

3 Comments & TrackBacks (Add yours)

The paper doll icon that precedes each comment is an idea conceived by Vanessa Tan.

Paper doll icon
Millarian » Blog Archive » Testing - flash.now gotcha's Gravatar

[…] Turns out that flash.now is cleared after it is rendered in the view. That means you cannot get the value out in your tests. There is a workaround though. It is discussed on the Rails wiki and on Chu Yeow’s blog. So what is the workaround? […]

Posted by: Millarian » Blog Archive » Testing - flash.now gotcha on January 25, 2007 2am

Paper doll icon
choonkeat's Gravatar

you can try object.blank? instead of object.nil? || object.empty?

Posted by: choonkeat on January 25, 2007 9am

Paper doll icon
Chu Yeow's Gravatar

Ahh thanks for the tip Choon Keat. Must have been a Railism, didn’t see it in the Ruby API :s

Posted by: Chu Yeow on January 25, 2007 10am

You can subscribe to the RSS feed for comments on this post.

Post a comment

(required)

(required, but never displayed)


You can format your comments using XHTML. Your email address will not be displayed or used for nefarious purposes.

Only following tags are allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>