I spent some time last week making the Koala test suite compatible with Rails 1.9/Minitest/RSpec 2/Rails 3. Along the way I encountered a few issues and learned a few lessons that may be useful to those making the same transition.
Undefined method ‘it’, ‘before’ or ‘after’ for MyTests:Class (NoMethodError)
These errors baffled me at first — I couldn’t figure out why my test classes, which worked fine with RSpec 1.3, threw errors on the most basic RSpec commands. Fortunately, these errors only happened for some of my test classes, and after some trial, error, and comparison I figured out out the cause. In RSpec 2, all tests and before/after blocks must be nested inside a describe block. RSpec 1.x was more forgiving, letting you write tests that lived directly inside the class.
class MyTests < Test::Unit::TestCase
it "should do stuff" do
@stuff.should be_a(Thing)
end
end
class MyTests < Test::Unit::TestCase
describe "basic stuff" do
it "should be do stuff" do
@stuff.should be_a(Thing)
end
end
end
Shared example groups are isolated
In the course of researching the previous issue, I stumbled across the following text tucked away at the bottom of the rspec-core upgrade guide:
NOTICE: The including example groups no longer have access to any of the methods, hooks, or state defined inside a shared group. This will break specs that were using shared example groups to extend the behavior of including groups in any way besides their intended purpose: to add examples to a group.
As it didn't help with my immediate problem I filed it away and moved on, but I was lucky I saw that. It turns out our test suite was doing exactly that what this change is meant to prevent: using shared example groups to set up context. In our case, we used a group to manage OAuth tokens and cleanup for live (or simulated live) testing. Moving the code from a shared example group into a module solved the problem. (See below.)
shared_examples_for "my tests" do
before :each do
@foo = Thing.new
end
end
class MyTests < Test::Unit::TestCase
it_should_behave_like "my tests"
describe "basic stuff" do
it "should do stuff" do
@foo.should be_a(Thing)
end
end
end
module MyTestHelper
def self.included(base)
base.class_eval do
before :each do
@foo = Thing.new
end
end
end
end
class MyTests < Test::Unit::TestCase
include MyTestHelper
describe "basic stuff" do
it "should do stuff" do
@foo.should be_a(Thing)
end
end
end
spec_helper and test classes
With Ruby 1.9.2, Minitest provides a backward compatible syntax that works with RSpec. Some of this is covered in the upgrade guide (link); I also found the BLOG POST (link) useful.
Conclusion
Overall, migrating Koala was quite painless; the gem itself required no changes and all the test suite changes were to form rather than substance. Upgrading Koala has made me very excited to get started with Ruby 1.9.2 and Rails 3, and I'm sure this won't be the last blog post on the subject.
Cheers,
Alex




