Skip to content

About

💉 Adds matcher support to minitest without all the other RSpec-style expectation "infections."

Topics

Resources

Contributing

Stars

39 stars

Watchers

1 watching

Forks

Repository files navigation

Minitest::MatchersVaccine

Gem Version Build Status Maintainability

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.

Installation

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

Compatibility

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.

Usage

Load the gem in your test_helper.rb after Minitest:

require "minitest/autorun"
require "minitest/matchers_vaccine"

Runnable example

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

Assertions and subjects

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:

  1. The explicitly supplied second argument, including false or nil.
  2. The @subject instance variable, if defined, including false or nil.
  3. The return value of the subject method, such as a Minitest::Spec subject { ... } 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.

Third-party matchers

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.

Minitest::Test

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
end

Minitest::Spec

require "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

Contributing

  1. Fork it ( https://github.com/rmm5t/minitest-matchers_vaccine/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Credits

The idea was originally inspired by the matcher assertions implementation in minitest-matchers.

License

MIT License

About

💉 Adds matcher support to minitest without all the other RSpec-style expectation "infections."

Topics

Resources

Contributing

Stars

39 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages