Black Bytes
Share this post!

A Quick Analysis of How Minitest Works

As you may know, Minitest is the default testing library for Rails & DHH’s favorite. Some people prefer it for its simplicity and how little code it has compared to its main ‘competitor’ (RSpec).

comparison chart minitest vs rspec

Now this post is not about which one you should choose or which is ‘better’. This post is about how Minitest actually gets the job done.

If you are wondering: Just use whichever you like the best, but you should still be familiar with both 🙂

So if you like to learn how things work you will enjoy this post, regardless of what testing library is your favorite.

Let’s Have a Look Under The Hood

One of the things that people recommend (including me) is to read source code because it’s a great way to learn how things work & also it’s a great way to pick up some new Ruby tricks that you may not have seen before.

So that’s what I did with Minitest & I’m going to share with you what I learned.

Let’s start with some actual test code so we can discuss how this relates to how Minitest does things.

So how does Minitest find these testing methods (like test_it_works) & run them? The answer is a little bit of metaprogramming ‘magic’:

This comes from the Runnable class which is defined in lib/minitest.rb. This code finds all the instance methods for the current class & selects the ones that match a regular expression.

So if you call methods_matching(/^test_/) you will get an array with all the method names that start with test_. Minitest does this for you & calls these methods.

That happens in the lib/minitest/test.rb file (and to be more specific, on the runnable_methods method, which also returns the list of methods in random order).

Important point:
This works because Minitest::Test is a subclass of Runnable.

The final piece of the puzzle is the run class method on Runnable, which does some additional filtering & then calls run_one_method with every method name & a reporter object.

Here’s the code:

And this ends up calling the run instance method on Minitest::Test:

Send is a metaprogramming method that lets you call another method on any object using a string or a symbol. The capture_exceptions block is used to record test failures & exceptions raised by your code.

This is how I like to read code, focus on one aspect or feature from the code you are reading & then keep peeling the layers off like an onion.

Conclusion

In this post you learned how Minitest uses metaprogramming to find your test methods & call them. You also learned how test errors & exceptions are captured into an array for reporting.

Do you like this kind of “code analyzed” articles? Let me know in the comments 🙂

Also don’t forget to share this on your favorite social networks & subscribe to my newsletter below if you aren’t already part of 1.800+ other Ruby developers like you that are looking to improve their skills!