Use RSpec-compatible matchers through Minitest assertions, without expectation-method infections on the objects under test.
Many testing libraries provide useful matchers for validations, associations,
and other behavior. This gem lets you reuse those matchers with assert_must,
assert_wont, must, and wont in your Minitest tests. These methods are added
to Minitest's assertions, without adding methods to the objects under test.
Why not use minitest-matchers? This gem is inspired by its matcher assertions and focuses on the four assertion helpers above.
Add this line to your application's Gemfile:
gem "minitest-matchers_vaccine"
And then execute:
$ bundle
Or install it yourself as:
$ gem install minitest-matchers_vaccine
Ruby 2.4 or newer and Minitest 5 or 6 are supported:
| Minitest | Ruby requirement |
|---|---|
| 5.x (minimum 5.0.0) | 2.4 or newer, with a Minitest release compatible with your Ruby version |
| 6.x | 3.2 or newer |
CI tests Minitest 5 on Ruby 2.4–2.7 and 3.0–4.0, and Minitest 6 on Ruby 3.2–4.0. Separate jobs pin Minitest 5.0.0 on Ruby 2.4 and 4.0 to verify the dependency's lower bound. Ruby versions earlier than 2.4 are no longer supported.
Third-party matcher libraries have their own Ruby and Minitest requirements.
Load the gem in your test_helper.rb after Minitest:
require "minitest/autorun"
require "minitest/matchers_vaccine"This example defines its own matcher, so it only needs Minitest and this gem.
Save it as even_test.rb and run bundle exec ruby even_test.rb:
require "minitest/autorun"
require "minitest/matchers_vaccine"
class BeEven
def matches?(subject)
@subject = subject
subject.even?
end
def failure_message
"expected #{@subject.inspect} to be even"
end
def failure_message_when_negated
"expected #{@subject.inspect} not to be even"
end
end
class EvenTest < Minitest::Test
def setup
@subject = 2
end
def test_explicit_subjects
assert_must BeEven.new, 4, "checking the total"
assert_wont BeEven.new, 3
end
def test_subject_helpers
must BeEven.new
wont BeEven.new, 3, "checking an odd value"
end
end| Assertion | Behavior |
|---|---|
assert_must(matcher, subject, message = nil) |
Passes when the matcher matches the explicit subject. |
assert_wont(matcher, subject, message = nil) |
Passes when the matcher does not match the explicit subject. |
must(matcher, subject = ..., message = nil) |
Like assert_must, with an optional subject. |
wont(matcher, subject = ..., message = nil) |
Like assert_wont, with an optional subject. |
must and wont choose their subject in this order:
- The explicitly supplied second argument, including
falseornil. - The
@subjectinstance variable, if defined, includingfalseornil. - The return value of the
subjectmethod, such as a Minitest::Specsubject { ... }declaration.
If no subject is supplied or defined, the call raises NoMethodError.
The optional third argument adds a custom message before the matcher's failure
message. To supply a custom message to must or wont, pass the subject
explicitly as the second argument, as shown above.
Install and configure the libraries that provide your matchers separately:
| Library and setup instructions | Matchers used below |
|---|---|
| shoulda-matchers | have_db_column, belong_to, have_many |
| valid_attribute | have_valid |
| strip_attributes | strip_attribute |
The following application examples assume your test helper loads the gem and
makes those matcher methods available in the test class or spec. They also
assume a User model with the corresponding database schema, associations,
validations, and attribute-stripping behavior.
require "test_helper"
class UserTest < Minitest::Test
def setup
@subject = User.new
end
def test_fields_and_associations
must have_db_column :name
must belong_to :account
assert_must have_many(:widgets), @subject
end
def test_validations
must have_valid(:email).when("a@a.com", "foo@bar.com", "dave@abc.io")
wont have_valid(:email).when(nil, "foo", "foo@bar", "@bar.com")
end
# Works with strip_attributes
def test_stripping
assert_must strip_attribute(:name), User.new
end
endrequire "test_helper"
describe User do
subject { User.new }
# Works with shoulda-matchers
it "has fields and associations" do
must have_db_column :name
must belong_to :account
must have_many :widgets
end
# Works with valid_attribute
it "validates" do
must have_valid(:email).when("a@a.com", "foo@bar.com", "dave@abc.io")
wont have_valid(:email).when(nil, "foo", "foo@bar", "@bar.com")
end
# Works with strip_attributes
it "strips attributes" do
must strip_attribute :name
end
end- Fork it ( https://github.com/rmm5t/minitest-matchers_vaccine/fork )
- 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 a new Pull Request
The idea was originally inspired by the matcher assertions implementation in minitest-matchers.