Ruby Minitest

I had the privilege of attending DCamp this past weekend. It was awesome. While doing the Game Of Life pairing sessions, one of my pair partners wanted to explore the exercise using Minitest. Neither of us had ever used it, so we moved on with RSpec and I made a note to come back to it.

I try to be discerning about bringing additional dependencies (including gems) into a project. I’ve always just used test/unit, and I prefer that syntax over the RSpec syntax. Minitest is baked into the stdlib (starting with Ruby 1.9.3), so you’ve already got everything you need. You can also write tests using either the test/unit or spec style. Win-win right? If you want more there are also additional gems that can supplement functionality. Everybody wins!!!

Here is a basic class, taken from the Minitest gem documentation.

lib/meme.rb

class Meme
  def i_can_has_cheezburger?
    "OHAI!"
  end

  def will_it_blend?
    "YES!"
  end
end

Unit tests, using Minitest:

test/test_meme.rb

require "minitest/autorun"
require_relative "../lib/meme"

class TestMeme < Minitest::Unit::TestCase
  def setup
    @meme = Meme.new
  end

  def test_that_kitty_can_eat
    assert_equal "OHAI!", @meme.i_can_has_cheezburger?
  end

  def test_that_it_will_not_blend
    refute_match /^no/i, @meme.will_it_blend?
  end

  def test_that_will_be_skipped
    skip "test this later"
  end
end

And a spec testing the same things:

spec/meme_spec.rb

require 'minitest/autorun'
require_relative "../lib/meme"

describe Meme do
  before do
    @meme = Meme.new
  end

  describe "when asked about cheeseburgers" do
    it "must respond positively" do
      @meme.i_can_has_cheezburger?.must_equal "OHAI!"
    end
  end

  describe "when asked about blending possibilities" do
    it "won't say no" do
      @meme.will_it_blend?.wont_match /^no/i
    end
  end
end

Outstanding. You can run either of these from the command line:

$ ruby spec/meme_spec.rb
Run options: –seed 25656

# Running tests:

..

Finished tests in 0.001430s, 1398.6014 tests/s, 2097.9021 assertions/s.

2 tests, 3 assertions, 0 failures, 0 errors, 0 skips

You can also use rake to run the tests, and this is the preferred method.

Rakefile

require 'rake/testtask'

Rake::TestTask.new(:spec) do |t|
  t.warning    = false    # this is the default -- shown as example of options
  t.verbose    = false
  t.test_files = FileList['spec/*_spec.rb']
end

Rake::TestTask.new(:unit) do |t|
  t.test_files = FileList['test/test_*.rb']
end

desc "Run ALL tests"
task :default do
  Rake::Task[:spec].invoke
  Rake::Task[:unit].invoke
end

Now you can ask rake what tasks it has for you:

$ rake -T
rake default # Run ALL tests
rake spec # Run tests for spec
rake unit # Run tests for unit

Cool. How about we just run the default rake task (ALLTHETESTS):

$ rake
Run options: –seed 28918

# Running tests:

..

Finished tests in 0.001187s, 1684.9200 tests/s, 2527.3799 assertions/s.

2 tests, 3 assertions, 0 failures, 0 errors, 0 skips
Run options: –seed 26846

# Running tests:

..S

Finished tests in 0.000936s, 3205.1282 tests/s, 3205.1282 assertions/s.

3 tests, 3 assertions, 0 failures, 0 errors, 1 skips

Awesome. You can also run all the tests, just a group of tests, or even just a single test file. This looks tasty enough to overtake test/unit as my go-to testing framework.

Leave a Comment

Filed under programming, ruby