If you’re familiar with unit testing tools (at least the ones based eventually on JUnit), you’ll immediately recognize the concept of testcase hooks, especially for setup and teardown. All of the testing frameworks for Ruby come with varying degrees of hook expressivity.
Rails provides an extension to the standard Test::Unit framework in the form of ActiveSupport::TestCase. One of the more powerful additions is callback queues of hooks. Instead of declaring a single setup method in a TestCase class, you can declare any number of setup and teardown callbacks.
Here’s a simple background example with vanilla Test::Unit that declares a setup hook:
class AverageTest < Test::Unit::TestCase def setup @records = [1, 2, 3] end def test_average_computes_correctly assert average(@records) == 2 end end
The test runner instantiates AverageTestCase, runs setup, and then runs test_average.
ActiveSupport::TestCase inherits from Test::Unit::TestCase, so the same can be stated:
class AverageTest < ActiveSupport::TestCase def setup @records = [1, 2, 3] end test "average computes correctly" do assert average(@records) == 2 end end
Written as a callback, that looks like:
class AverageCallbackTest < ActiveSupport::TestCase setup do @records = [1, 2, 3] end test "average computes correctly" do assert average(@records) == 2 end end
There’s a nasty gotcha in here: if we subclass AverageCallbackTest, and include another setup hook in the callback, everything works as expected: both setup hooks run. But, if we subclass AverageTest, and define a new setup method, the superclass’s setup method will be overridden.
We recommend that you use callback queues instead of setup methods, where possible. They create fewer opportunities for subtle failures.