Fixing the test setup bug in Rails 2.0.2
May 13, 2008Help! My setup method is not running!
Much to my annoyance (and seemingly, very few other developers), Rails 2.0.2 introduced a bug in ActionController::TestCase — setup methods for tests are not run. It worked in Rails 2.0.1, and broke in Rails 2.0.2. This was fixed in the very next changeset, Revision 8442, but mysteriously it was never rolled out in a 2.0.3. That was five months ago, and given that this basically breaks all tests it’s pretty mysterious that there is still no released version of Rails with this bug fixed.
(NOTE: This was true when written. Now, Rails 2.1 is out, and it includes the fixes. You can use the workarounds below if your project depends on Rails 2.0.2, otherwise I recommend that you simply upgrade to 2.1!)
I’m pretty sure I’m not the only Rails developer who writes tests! So I’m surprised there hasn’t been more of an outcry about this bug. But the Rails dev process has always been rather mysterious to me. So: we need a workaround. I know of two.
Option one: subclass Test::Unit::TestCase
This is what I’ve been doing till now: just going back and writing my tests Rails 1.x style. It’s annoying and clunky: the whole point of ActionController::TestCase in Rails 2.0 was to eliminate all the redundant and non-DRY junk you had to put in your test setup to establish the instance variables @request, @controller, etc. In any case, it looks like this:
class FooControllerTest < Test::Unit::TestCase
fixtures :tasks, :users, :people
def setup
super
@controller = FooController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
# ... your setup code here ...
end
Option two: use a revision from edge with the bug fixed
Normally, I abhor using unreleased software in a production environment. I definitely don’t use EDGE rails in my released software for clients in general … the hassle is too much to maintain with the constant changesets. I’d rather understand and work with stable software, even if that means I’m not one of the cool Rails edgerati: stable software for my customers is the higher priority.
However, in this case I’m making an exception, and I’ve started using revision 8442 of Rails as if it were a released 2.0.3, because this bug just annoys me too much. Installing it is simple. If you’re using frozen Rails in your application (and you should be!), it’s just this at the command-line, in your application root:
$rake rails:freeze:edge REVISION=8442
That should give you a “2.0.3″ that fixes this irritating bug and lets you write your tests and setup the way God intended:
class FooControllerTest < ActionController::TestCase
fixtures :tasks, :users, :people
def setup
super
#... your setup code here ...
end
Don’t forget the call to super, otherwise you’ll clobber the setup method in ActionController::TestCase and your tests won’t work.
Important note for subversion users!!
If you are maintaining your project in subversion, re-freezing your rails code with the above command will hose all of your .svn/ directories under vendor/rails. This will give you a few minutes of headaches as you get things straightened back out. I recommend deleting your old rails freeze first, committing, and then re-freezing:
$svn rm vendor/rails
$svn commit -m "removed old rails version"
$rake rails:freeze:edge REVISION=8442
$svn add vendor/rails
$svn commit -m "froze rails to revision 8442"
I maintain most of my projects in Git, now, so this wasn’t a problem, but I wasn’t thinking when I converted one of my older projects that’s still in svn. It was definitely a headache when the working repository broke, so avoid that if you can.
So there you go. I never thought I’d recommend using unreleased software in production, but just hold your nose and pretend that Rev 8442 is “Rails 2.0.3″ and you’ll probably be fine. I haven’t found any problems with it, myself.