Published 2015-04-14 @ 12:00
minitest/spec has existed since v1.3.0 (6.5 years). It started as a
simple proof of concept to show that there was a 1:1 mapping between
“spec-style” and “unit-style” tests (not to be confused with BDD vs
TDD, which is a development process). It showed (in 67 lines!), that
describe was just a Test subclass, and every
it was just a
test method (with strange inheritance).
minitest/spec has only grown to 152 lines since then but it really
hasn’t changed all that much. Until yesterday.
The older spec system relied on a thread-local variable in order to understand what the current test method was. It was a limitation of how you called the expectation methods. So, when you wrote a test like this:
must_equal on the result of
1+1. This implies that the
method is on Object in order to be called on the value
2. In order
must_equal back to
minitest needed to know what test the expectation was in and that was
Minitest::Spec.current, which just accesses a thread-local
variable. That works great 99.9% of the time, until, you know, you use
threads in your tests. (Why you would use threads inside your tests is
So, if your test changed to this:
describe Something do it "should blah-blah threaded" do my_threaded_test_thingy do (1+1).must_equal 2 end end end
then it would blow up, because you’d be wrapping
must_equal in your
own thread and that would make the thread-local variable unavailable
(they’re not scoped to parent threads, for better or worse).
Yesterday’s release of 5.6 brings new expect system from tenderlove
that adds a struct and one new method
_. The method wraps the
resultant value in a Expectation value monad. All in all, it only adds
11 lines of code to minitest. All of the usual expectation methods are
defined, but this time around, they know what test they’re in because
it was stored off when the monad was created.
So, one character change later, and the following works:
describe Something do it "should blah-blah threaded" do my_threaded_test_thingy do _(1+1).must_equal 2 end end end
_ is also aliased to
value if you prefer verbier tests.
It is also aliased to
expect, to make transitioning easier, but
<bikeshed>1I really dislike that name</bikeshed> because it is
value is much better, and imo,
_ is even better
because it gets out of your way and lets you focus on the actual meat
of the test.
At some point (pre-6.0) the old expectations are going to be deprecated in favor of the new system. Until then, they’re fine to use and won’t make any noise until the deprecation is officially planned. That will remove the monkeypatches on Object for all of the expectations that minitest supports. Hopefully that’ll reclaim the 11 lines we added.
Apologies are owed to Dickens. I couldn’t help myself, even tho I hated that book.
<bikeshed> means: don’t argue with me about it. I don’t care to argue about it. ↩