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)