MiniTest is an awesome testing framework. It's small, fast, and has very little magic.
There are two hard things in Computer Science: cache invalidation and naming things. — Phil Karlton
Unfortunately, MiniTest fails at the latter.
What?
minitest-english
provides a simple interface for defining aliases in MiniTest assertions, expectations, and other modules/classes. It also optionally augments MiniTest's default assertion and expectation naming with semantically symmetric aliases.
Why?
Assertions
MiniTest provides a variety of positive and negative assertions:
assert_equals true, true
refute_equals true, false
assert_nil nil
refute_nil true
# etc.
"Refute" is not an antonym of "assert." Refutation requires proof, not just assertion.
Expectations
Every assertion has an aliased expectation:
true.must_equal true
true.wont_equal false
nil.must_be_nil
true.wont_be_nil
# etc.
"Must" is present tense but "wont" (contraction of "will not") is future tense.
How?
minitest-english
provides an interface for watching and aliasing methods in MiniTest::Assertions, MiniTest::Expectations, and other modules. Once a module/class and aliasing rule is registered with MiniTest::English
, all current and future methods in the module/class that match the rule will be aliased according to that rule.
minitest-english
also optionally aliases all refute
assertions with deny
assertions and all wont
expectations with must_not
expectations.
It's simple and does not use method_missing
or any other inefficient techniques.
Installation
Add this line to your application's Gemfile:
gem 'minitest-english'
And then execute:
$ bundle install
Require it in your test_helper or spec_helper:
require 'minitest/english'
To alias all refute*
assertions to deny*
assertions:
require 'minitest/english/deny'
To alias all wont*
expectations to must_not*
expectations:
require 'minitest/english/must_not'
Usage
Registering assertions and expectations
The basic format is:
MiniTest::English.register_assertion/expectation, matcher_string, replacement_string
Let's register an expectation:
MiniTest::English.register_expectation "wont*", "must_not*"
That will alias all expectations that begin with wont
to ones that begin with must_not
. register_assertion
works the same way.
Advanced registrations
MiniTest::English
's register_assertion
and register_expectation
methods are just sugar that transform their input and send it to MinTest::English.register
.
MiniTest::English.register
takes a module/class, a regex that matches undesirable methods and captures the desirable parts of those methods, and a block that receives the captures and returns a symbol/string of the new method name.
These two methods produce the same result:
MiniTest::English.register_expectation "wont*", "must_not*"
MiniTest::English.register MiniTest::Expectations, /\Awont(.*)\z/ do |captures|
:"must_not#{captures[0]}"
end
MiniTest::English.register
is provided as a more flexible but verbose interface to deal with other classes/modules and other edge cases.
deny & must_not
minitest/english/deny
Write your negative assertions with deny
.
require 'minitest/english/deny'
refute_equal "English", "Do you speak it?"
# refute* becomes deny*
deny_equal "English", "Do you speak it?"
minitest/english/must_not
Write your negative expectations with must_not
.
require 'minitest/english/must_not
"Do you speak it?".wont_equal "English"
# wont* becomes must_not*
"Do you speak it?".must_not_equal "English"
Caveat
Perhaps you prefer geometric equality to semantic equality.
"assert".length == "refute".length
"must".length == "wont".length
If so, use minitest-english
anyway and make your middle school English teacher proud.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request