Minitest with Ruby and Ruby on Rails 4

Configuring Minitest in Rails 4

I've recently been making the move from Ruby on Rails 3 to Ruby on Rails 4 and from rspec to minitest-spec. I've found the following setup to work fairly well. As I've been working on a Ruby client / Rails server project I decided it was worth documenting the minor differences. It needed slight tweaking from what I've found documented on other sites to get some of the shortcuts in vim-rails working. The turn gem is included because I like the output better as well as the differences between a current Ruby on Rails test helper and a straight Ruby test helper.

Rails 4 Configuration

Steps to set up minitest-spec in a Ruby on Rails 4 project:

  • Name the test folder "test" (not "spec")
  • Symlink spec to test
  • Gitignore the spec link
  • Tests should end with _spec.rb

The symlink and test vs spec folder is important to keep vim-rails on track with the alternate (:A) and related (:R) files.

Install minitest-spec

1 gem install minitest-rails
2 rails g mini_test:install

test/test_helper.rb

Remove the devise section if not relevant.

 1 ENV["RAILS_ENV"] = "test"
 2 require File.expand_path("../../config/environment", __FILE__)
 3 require "rails/test_help"
 4 require "minitest/rails"
 5 require "minitest/spec"
 6 
 7 begin
 8   require 'turn/autorun'
 9   Turn.config.format = :progress
10 rescue LoadError
11   p 'failed to load turn'
12 end
13 
14 class ActiveSupport::TestCase
15   fixtures :all
16 end
17 
18 class ActionController::TestCase
19   include Devise::TestHelpers
20 end

lib/tasks/minitest.rake

 1 WARN = false
 2 
 3 Rake::TestTask.new do |t|
 4   t.name = "spec"
 5   t.libs << "test"
 6   t.pattern = "test/**/*_spec.rb"
 7   t.verbose = true
 8   t.warning = WARN
 9 end
10 
11 Rake::TestTask.new do |t|
12   t.name = "spec:controllers"
13   t.libs << "test"
14   t.pattern = "test/controllers/*_spec.rb"
15   t.verbose = true
16   t.warning = WARN
17 end

Running specs from Vim

Regardless of whether it's a Ruby project or a Rails project I like to be able to run specs through Rake with a Vim shortcut. Add this snippet to your ~/.vimrc. <leader> corresponds to the 'mapleader' variable. Type 'let mapleader' to display your leader key. Mine is ',' so pressing comma followed by 'r' will execute 'rake spec'.

nnoremap <leader>r :!rake spec<CR>

Minitest-spec in a simple Ruby project

Configuring specs in a simple Ruby project is very similar to what is demonstrated above. Use this to get started. I've included turn again with the progress format as it is my preference.

test/test_helper.rb

1 require 'minitest/spec'
2 require 'minitest/autorun'
3 
4 begin
5   require 'turn/autorun'
6   Turn.config.format = :progress
7 rescue LoadError
8   p 'failed to load turn'
9 end

test/unit/whatever_spec.rb

1 require_relative '../test_helper'
2 ...

Standard Ruby Rakefile

Adding this Rakefile will keep things consistent with the Ruby on Rails approach above. It'll also allow the vim shortcut defined above to operate here as well.

 1 require "bundler/gem_tasks"
 2 require 'rake/testtask'
 3 
 4 Rake::TestTask.new do |t|
 5   t.name = "spec:all"
 6   t.libs.push ["lib", "spec"]
 7   t.test_files = FileList['spec/**/*_spec.rb']
 8   t.verbose = true
 9   t.warning = true
10 end
11 
12 Rake::TestTask.new do |t|
13   t.name = "spec:unit"
14   t.libs.push ["lib", "spec"]
15   t.test_files = FileList['spec/unit/*_spec.rb']
16   t.verbose = true
17   t.warning = true
18 end
19 
20 Rake::TestTask.new do |t|
21   t.name = "spec:integration"
22   t.libs.push ["lib", "spec"]
23   t.test_files = FileList['spec/integration/*_spec.rb']
24   t.verbose = true
25   t.warning = true
26 end
27 
28 desc "defaults to run all specs"
29 task :spec => ["spec:unit", "spec:integration"]

Minitest Matchers

I find that I am able to accomplish most of what I want in testing with only a few of these matchers. As I'm converting to minitest, I figured I might as well keep a list of matchers around to expand my own options. To test negative expectations substitute 'wont' for 'must' above. Here is the list:

  • lambda.must_be_silent
  • lambda.must_output(stdout, [stderr..])
  • lambda.must_raise(exception)
  • object.must_be_close_to
  • object.must_be_empty
  • object.must_be_instance_of(klass)
  • object.must_be_kind_of(klass)
  • object.must_be_nil
  • object.must_be(operator_as_symbol, expected_value)
  • object.must_be_same_as
  • object.must_be_within_delta
  • object.must_be_within_epsilon
  • object.must_equal(other)
  • object.must_include(other)
  • object.must_match(regex)
  • object.must_respond_to(message)
  • object.must_throw(sym)
comments powered by Disqus