Using MiniTest::Spec With Rails
So after a few blog post on the subject of MiniTest::Spec, I finally have a simple testing stack for Rails 3 that leverages MiniTest's
spec DSL. I introduce to you the MiniSpecUnit gem. MiniSpecUnit defines a
Test::Unit::TestCase class that subclasses MiniTest::Spec. It implements only what is needed to make rails happy. It is not
a drop in replacement for the real Test::Unit::TestCase that is included with ruby 1.9.
Once you bundle the gem in your Rails application, it will satisfy the require "test/unit/testcase" from ActiveSupport's
test case. Tricking it to use MiniTest::Spec instead of MiniTest::Unit. Here is an example Gemfile that shows the usage of MiniSpecUnit
as well as two other MiniTest gems that I have made. The first is MiniBacktrace which allows you to leverage the
Rails.backtrace_cleaner using MiniTest. The other is MiniShoulda which builds a simple Shoulda syntax on top of
MiniTest::Spec.
group :test do
gem 'minitest' # At least v2.0.2 if using MiniShoulda.
gem 'mini_specunit' # The goods! Force MiniTest::Spec instead of MiniTest::Unit.
gem 'mini_backtrace' # Use Rails.backtrace_cleaner with MiniTest.
gem 'mini_shoulda' # A small Shoulda syntax on top of MiniTest::Spec.
end
Since MinitTest::Spec is built on top of MiniTest::Unit, there is not a lot that can go wrong. With MiniSpecUnit, we finally have a
working solution by replacing MiniTest::Spec as the superclass for ActiveSupport::TestCase when using Rails. This solution is drop dead
simple and does not require you to recreate a new test case in your test_helper.rb and change all your cases to subclass
that new test case. About the only gotcha is a few missing assertions available in Test::Unit. If you encounter these, I encourage you to
rewrite them to the modern MiniTest::Spec assertion style. I commonly use this cheat
sheet to remember them. For example:
# This:
assert_not_nil @foo.bar
# Would Become This:
@foo.bar.wont_be_nil
Functional Tests With ActionController::TestCase
One problem you may have with your functional tests is a nil @controller instance variable in describe or
context blocks. Resulting in the "RuntimeError: @controller is nil: make sure you set it in your test's setup
method." message. This is easy to fix, all you have to do is be explicit about your controller that you are testing like so.
class UsersControllerTest < ActionController::TestCase
tests UsersController
...
end
Broken Describe Scopes
In my article, From Test::Unit & Shoulda To MiniTest::Spec & MiniShoulda, I cover a patch to MiniTest that would fix "undefined local variable or method" errors when using describe/context scopes. I submitted a patch and pull request to Ryan Davis that I believe was applied. At the time of this article, there is no release version of MiniTest that includes this patch that I have in MiniShoulda. So if you find yourself with errors in describe/context blocks, consider bundling the MiniSholda gem to fix it till a new version of MiniTest is released.
In Closing
I have only tested the above stack in the latest Rails edge, 3.1.beta and ruby 1.9.2. I doubt there are issues on older versions of Rails with different Ruby versions. If you apply these gems to success, I would love to hear about it. Happy testing!