Get the most out of Test::Unit
As mentioned before, I’ve been considering a complete switch back to Test::Unit. Well, all new projects since that post have test/unit tests, but I’ve yet to decide if it’s worth converting old projects. Probably not, but we’ll see.
Coming from Rspec, there were a few things I really missed:
- block structure for writing tests
- really easy to test helpers
- pretty test output when running tests
- ability to record tests in a specdoc format
Well, it turns out that it’s not that hard to get those niceties in test/unit.
Block structure for writing tests
It’s now built-in to Rails test support, so tests now look like this:
1 2 3 | test "should have some behavior" do # test some behavior end |
And if you’re on a stand-alone Ruby project, here’s the implementation.
In addition, Rspec also provides that before do and after do syntax for pre/post operations. As you know, test/unit has the setup and teardown methods. But you can easily convert those to accept a block:
1 2 3 4 5 6 7 8 9 | class Test::Unit::TestCase def self.setup(&block) define_method(:setup, &block) end def self.teardown(&block) define_method(:teardown, &block) end end |
Since, originally, all you’re doing is overriding the methods with your own definition, this just automatically works.
Really easy to test helpers
This could be blatantly obvious to those familiar with test/unit, but I don’t think this was available early on. Either way, there’s now built-in support for testing helpers in your Rails projects, you just have to bring it to life. Here’s how:
1 2 3 4 5 6 7 8 9 10 11 12 13 | # test/test_helper.rb require 'action_view/test_case' # test/helpers/application_helper_test.rb class ApplicationHelperTest < ActionView::TestCase test "should set page title with a block" do result = page_title do '<em>Heading</em>' end assert_equal '<h1><em>Heading</em></h1>', result end end |
As you can see, all you have to do is inherit from ActionView::TestCase. And to run these tests, here’s a rake task:
1 2 3 4 5 6 7 8 | namespace :test do Rake::TestTask.new(:helpers) do |t| t.libs << "test" t.pattern = 'test/helpers/**/*_test.rb' t.verbose = true end Rake::Task['test:helpers'].comment = 'Run the helper tests in test/helpers' end |
A simple $ rake test:helpers should do the trick.
Pretty test output and specdoc testdoc
I’m going to mention the last two bullets in one section. While this isn’t the most sophisticated solution, if you have the “colored” and “redgreen” gems installed, you can get a pretty decent test output using this rake task:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | require 'colored' def banner(title, pad = 85) puts "\n#{title} ".ljust(pad, "*").yellow end def stripe puts ("-" * 84 + "\n").yellow end namespace :test do Rake::TestTask.new(:helpers) do |t| t.libs << "test" t.pattern = 'test/helpers/**/*_test.rb' t.verbose = true end Rake::Task['test:helpers'].comment = 'Run the helper tests in test/helpers' end namespace :tests do desc "Documents all tests in doc/TESTDOC" task :doc do File.open(Rails.root + '/doc/TESTDOC', 'w') do |file| Dir.glob('test/**/*_test.rb').each do |test| test =~ /.*\/([^\/].*)_test.rb$/ file.puts "#{$1.gsub('_', ' ').capitalize}:" if $1 File.read(test).map { |line| /test "(.*)" do$/.match line }.compact.each do |t| file.puts " - #{t[1]}" end file.puts end end end desc "Execute all application tests, plus TESTDOC" task :run do # document a list of all executed tests # (used to match up with requirements) Rake::Task['tests:doc'].invoke # unit tests banner "EXECUTING UNIT TESTS" Rake::Task['test:units'].invoke stripe # functional tests banner "EXECUTING FUNCTIONAL TESTS" Rake::Task['test:functionals'].invoke stripe # helper tests banner "EXECUTING HELPER TESTS" Rake::Task['test:helpers'].invoke stripe # integration tests banner "EXECUTING INTEGRATION TESTS" Rake::Task['test:integration'].invoke stripe # performance tests banner "EXECUTING APPLICATION BENCHMARKS" Rake::Task['test:benchmark'].invoke stripe end end |
Just put that in a file called “tests.rake” and stick it in your lib/tasks/ directory. Then type $ rake tests:run from your project root. If all goes well, you’ll see something like this (excuse the lack of tests, this is from a somewhat fresh project at work):

As an added bonus, the task also records all of the tests into a TESTDOC file within the doc/ directory of your Rails application. Again, it’s not like this file is super sophisticated, but it serves as a list for all of the tests that your application is accountable for. Sometimes useful for mapping requirements to tests, if you have to deal with that sort of thing :-)
I’m always seeking improvements for things like this, so let me know if you have any thoughts and/or additions. You can find the rake task in gist format, so feel free to fork it and make it better.
And just to be complete, Jeremy McAnally has written several testing libraries that fit very well with test/unit (namely, context, stump, and matchy), so keep those in mind, too.
Happy testing!

Chris Tuesday, 03 Mar, 2009 Posted at 07:57PM
I’ve grown to love the simplicity of test/unit lately. I’m also playing around with shoulda as a lighter-weight alternative to rspec.
Just a note about helper tests – the common practice is to just drop them into test/units/helpers – rake test:units will pick them up automatically. A custom rake task was my original approach, but the subdirectory way is nice since it’s automatic.