Invent

MiniTest – Ruby’s New BFF





MiniTest is the new testing framework that ships with Ruby 1.9. It’s fast, robust, and wants you to use it. In this blog post, I’ll show you how to write a simple test in a Test:Unit syntax and also in “RSpec” syntax.

*DR*
Ruby 1.8′s standard library came with Test::Unit.

Test::Unit was written in 2003 and is lacking in some features that most modern projects need, such as, mocking and machers. In addition, it’s slow and bloated with UI libraries that are rarely used as “GTk” and “FxRuby

Speed is crucial when it comes to unit tests. Michael Feathers, in “Working Effectively With Legacy Code” wrote: _”A unit test that takes 1/10th of a second to run is a slow unit test… If [unit tests] don’t run fast, they aren’t unit tests.”_ In my experience, if your unit test takes more than 10 seconds, there is a good chance you’ll stop running them.

Ruby 1.9 comes with a drop in replacement for Test::Unit called “MiniTest“. Its goal is to be very fast, clean and explicit.

The codebase is very small – “unit.rb” (the main file) is only 723 lines of code. The framework consists of 4 files that you can pick and choose which one you want to use:
* minitest/unit – The core. It gives you a nice set of assertion methods.
* minitest/spec – If you like the RSpec/Shoulda DSL, you want to require this one.
* minitest/mock – Tiny mock object framework.
* minitest/benchmark – Set performance requirements for your methods.

Let’s see MiniTest in action – using the test-first approach. (If you don’t use Ruby 1.9, you can still use MiniTest by installing the minitest gem.)

Create test_reddit.rb file and add the following:

gist: 824033

Let’s explain what’s going on here. For those who are coming from Test::Unit, it should look familiar. For the rest of us, all we did was inherit our test class from MiniTest::Unit::TestCase. You don’t have to prefix your class with Test, but it’s a good convention. Next, we have a setup method. This is a special method that MiniTest knows about and will run before each test method in this class.

Test_hot_story is our first test Method. Notice that here we must prefix our method with test. If we don’t, it will be ignored. Inside our method we assert_equal, which will fail if the first argument is different from the second. In our case, we want to make sure we get the hottest Reddit story when calling @reddit.hot.

Let’s run our test now. We do it simply by running our test file: ruby test_reddit.rb.

Here is the output:

Finished in 0.001100 seconds.
1) Error:test_hot_story(TestReddit):NameError:
uninitialized constant TestReddit::Reddit
test_reddit.rb:5:in 'setup' 1 tests, 0 assertions,
0 failures, 1 errors, 0 skips Test run options:
--seed 52515

Our test failed since we don’t have the Reddit class. Before creating it, let’s look at the last line of the output. MiniTest will run our test suite in random order to avoid accidental dependency between some tests. If you notice weird errors, you can run your tests again with the seed number to reproduce the same order of tests.

Let’s write the smallest possible code that will pass our test. Create reddit.rb file with the following:

gist: 824035

And require it in the test_reddit.rb file: require_relative ‘reddit’ (Ruby 1.9 doesn’t add the current dir to the load path, so require ‘reddit’ will not work). Let’s run our test again and enjoy our first success – our test passes!

Two Tips:
* If you want green/red colors in the output, use the “redgreen gem
* If you want the output to include the time it takes to run each method, use -v.

Lately, I want to show you how to use MiniTest with different syntax that looks similar to RSpec. Let’s replace our test_reddit.rb with this file:

gist: 824164

Let’s run it to make sure it passes. Nice – it does! If you prefer the RSpec syntax and want your ‘before,’ ‘describe’ and ‘it’ blocks back, your heart is probably dancing with joy now.

That’s it for the quick introduction to MiniTest. I hope I convinced you to give it a try. And if you do, don’t forget to try the mocking utility in minitest/mock.

Thanks to Adam Avilla from “LA Ruby Conf” for the inspiration and Ryan Davis for writing MiniTest.

Leave a Reply

Your email address will not be published. Required fields are marked *

Learn More

On Facebook

Recent Tweets

Follow Us

Scroll to top