MiniTest is the preferred method of testing in Ruby 1.9.3 and up. Ruby is currently at version 2.1.2, so if you haven’t taken a look at MiniTest just yet, I recommend checking it out. There are some compelling features of MiniTest that make it a viable option as a testing library:
Test::Unit Compatibility
MiniTest supports assertions and test cases just like its predecessor Test::Unit. If an existing test suite is written in Test::Unit, conversion is relatively easy and painless.
Expectation Syntax
In addition to the assert syntax, MiniTest supports an expectation syntax similar to RSpec. The expectation syntax is largely a preference for each individual developer (or team), and there is no need to pull in an external library.
Test Benchmarking
MiniTest supports performance benchmarking out of the box. As the documentation states, “you can assert that your newb co-worker doesn’t replace your linear algorithm with an exponential one!”
Mocking and Stubbing
Mocking and stubbing are built-in to MiniTest! There’s no need to add in any separate libraries.
Contents
Writing Your First Test
In this section, we’re going to write a simple class and a test for it. This will give us an idea of how MiniTest works.
Let’s take a look at following simple class (blog.rb
):
class Blog def title "Treehouse Blog" end end
Writing a test for it is simple using MiniTest. Here’s blog_test.rb
:
require 'minitest/autorun' require './blog' class TestBlog < Minitest::Test def setup @blog = Blog.new end def test_title_is_treehouse assert_equal "Treehouse Blog", @blog.title end end
We run it the following way:
ruby blog_test.rb
And you should see:
$ ruby blog_test.rb Run options: --seed 30102 # Running: . Finished in 0.000980s, 1020.4082 runs/s, 1020.4082 assertions/s. 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
Writing Your First Expectation
MiniTest also supports the option of writing tests in the expectation style. If you’ve used RSpec, the syntax is similar and you’ll feel right at home with describe
and it
blocks. Here’s what the same test would look like when writing as an expectation (blog_spec.rb
):
require 'minitest/autorun' require './blog' describe Blog do before do @blog = Blog.new end describe "#title" do it "returns the title of the blog" do @blog.title.must_equal "Treehouse Blog" end end end
Run it the same way:
$ ruby blog_spec.rb Run options: --seed 19668 # Running: . Finished in 0.001998s, 500.5005 runs/s, 500.5005 assertions/s. 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
Supported Assertions and Expectations
There are a ton of different assertions that are supported in Minitest. Some of the assertions that you’ll be using most often are:
Assertion | Expectation |
---|---|
assert_equal |
must_equal |
assert_instance_of |
must_be_instance_of |
assert_nil |
must_be_nil |
assert_raises |
must_raise |
See the documentation for a complete list of assertions and expectations.
MiniTest and Rails
Using MiniTest with Rails is completely supported. It takes a slight bit of setup to get working, however, it is just as easy as using something like RSpec. There are a couple of different options when using MiniTest
with a Rails application. The first one we’ll take a look at is minitest-rails. Setup is straightforward in this library. To install, open up your Gemfile
and place the following:
gem "minitest-rails"
Then install it:
bundle install rails generate minitest:install
It’s also possible specify using the expectation format by default in config/application.rb
:
config.generators do |g| g.test_framework :minitest, spec: true end
Your application will now have minitest files generated by default when you run the rails generate
command. Easy!
Another library worth looking at is minitest-spec-rails. This library accomplishes the same thing as the minitest-rails
gem. However, minitest-spec-rails has slightly different priorities which you can read about in the Readme. Either library works, and I encourage you to read both project’s documentation and decide which may be a better fit for your project.
Try It!
There are a wealth of testing options in the Ruby community. For a while, it seemed like a new testing library popped up every day. If you’re going to be doing Ruby development, it is important to be familiar with the standard testing library that ships with the language. If you haven’t given MiniTest
a try, check it out! You just may like what you see.
Update: Ryan Davis has pointed out that in MiniTest 4, tests should inherit from MiniTest::Unit::TestCase
and in MiniTest 5, tests should inherit from Minitest::Test
. The code in the article has been updated to reflect this. Thanks, Ryan!
Why is it the testing code is always bigger/longer than the code being tested. Which is why all these test frameworks are ridiculous.
This is a strange sort of dismissal: why should testing code be smaller than the code it tests? When they test cars with crash test dummies, it takes far more time and resources than manufacturing a single car – special equipment, experts in metallurgy, and so on.
Tests save me huge amounts of time – running umpteen scenarios I might inadvertently break with my code changes.
If your complaint is that tests take a lot more maintenance than the code they test (which would be a more sensible complaint) then that suggests your code design might need to be more test-friendly.
Ruby itself is part of the problem: because it has no real support for static checking, you have to test all code as if it’s dynamic. Contrast this with Groovy, and more recently Python, where you can mark parts of your code as static and benefit from the computer catching things like type errors.
Hey Jason,
This is a great soft intro! Do you have any recommendations for learning MT besides the docs? It seems everything I find is catered to people who already know testing.
Ryan, I use what ever is best suited for the project. I like RSpec’s new expectation syntax but don’t have a strong preference.
Jason, which library do you use for testing and why?