Mike Mazur Dev Notes

Hello Minitest

I have heard nice things about Minitest in the past, but have always worked with RSpec. Working on a small CLI utility recently, I wanted to minimize external dependencies, and since Minitest is built in to Ruby1 I thought I’d give it a shot.

Minitest allows you to run the tests directly from the command line. I started with this approach, test-driving a specific piece of logic I had in my head. Later I followed Bundler’s excellent documentation for writing a gem and adopted a Rakefile.

Spec or Unit Test Notation?

I started using the spec notation at first, but noticed that the error messages refer to auto-generated methods. Consider the following test:

require 'minitest/autorun'

describe 'Foo' do
  it 'fails' do
    1.must_equal 0
  end
end

Running it generates this output:

$ ruby foo_test.rb
Run options: --seed 64703

# Running:

F

Failure:
Foo#test_0001_fails [foo_test.rb:5]:
Expected: 0
  Actual: 1


bin/rails test foo_test.rb:4



Finished in 0.001004s, 996.0157 runs/s, 996.0157 assertions/s.
1 runs, 1 assertions, 1 failures, 0 errors, 0 skips

That failure description references Foo#test_0001_fails. I found this slightly disorienting even with a small amount of code, and it hinders navigating to the failing test by copying the method name from the error message and searching for it. I decided to switch to the regular unit test notation:

require 'minitest/autorun'

class Foo < Minitest::Test
  def test_fails
    assert_equal 0, 1
  end
end

It reminds me of how I first learned unit testing, through JUnit examples2. The error report is clearer:

Failure:
Foo#test_fails [foo_test.rb:5]:
Expected: 0
  Actual: 1

The notation also affects the assertion syntax.

Running Specific Tests

Once there were multiple test files, the need arose to run specific test files and specific tests on their own. A web search eventually led me to a post by Weston Ganger which provides the solution.

How it works: the TEST option tells rake which file to run, while the value of the TESTOPTS option is passed on to the test runner. The options Minitest accepts are documented.

References

  1. Minitest started shipping with Ruby 1.9. The docs do mention, though, that not all gem functionality works with the built-in Minitest, so installing the gem might be best. 

  2. I actually first encountered unit testing in Python, but reading Kent Beck’s Test-Driven Development: By Example really solidified things for me. I recommend this book to anyone starting out with unit testing.