Matchi

Version Yard documentation CI RuboCop License

Collection of expectation matchers for Rubyists 🤹

A Rubyist juggling between Matchi letters

Project goals

  • Provide a collection of useful generic matchers.
  • Adding matchers should be as simple as possible.
  • Being framework agnostic and easy to integrate.

Installation

Add this line to your application's Gemfile:

gem "matchi"

And then execute:

bundle

Or install it yourself as:

gem install matchi

Overview

Matchi provides a collection of damn simple expectation matchers.

Usage

To make Matchi available:

require "matchi"

All examples here assume that this has been done.

Anatomy of a matcher

A Matchi matcher is just an object that responds to the matches? method with a block as argument, and returns a boolean. That's all it is.

But let's see some examples.

Built-in matchers

Equivalence matcher:

matcher = Matchi::Eq.new("foo")
matcher.matches? { "foo" } # => true

Identity matcher:

matcher = Matchi::Be.new(:foo)
matcher.matches? { :foo } # => true

Regular expressions matcher:

matcher = Matchi::Match.new(/^foo$/)
matcher.matches? { "foo" } # => true

Expecting errors matcher:

matcher = Matchi::RaiseException.new(NameError)
matcher.matches? { Boom } # => true

Type/class matcher:

matcher = Matchi::BeAnInstanceOf.new(:String)
matcher.matches? { "foo" } # => true

Change matcher:

object = []
matcher = Matchi::Change.new(object, :length).by(1)
matcher.matches? { object << 1 } # => true

object = []
matcher = Matchi::Change.new(object, :length).by_at_least(1)
matcher.matches? { object << 1 } # => true

object = []
matcher = Matchi::Change.new(object, :length).by_at_most(1)
matcher.matches? { object << 1 } # => true

object = "foo"
matcher = Matchi::Change.new(object, :to_s).from("foo").to("FOO")
matcher.matches? { object.upcase! } # => true

object = "foo"
matcher = Matchi::Change.new(object, :to_s).to("FOO")
matcher.matches? { object.upcase! } # => true

Satisfy matcher:

matcher = Matchi::Satisfy.new { |value| value == 42 }
matcher.matches? { 42 } # => true

Custom matchers

Custom matchers can easily be added to express more specific expectations.

A Be the answer matcher:

module Matchi
  class BeTheAnswer
    def matches?
      42.equal?(yield)
    end
  end
end

matcher = Matchi::BeTheAnswer.new
matcher.matches? { 42 } # => true

A Be prime matcher:

require "prime"

module Matchi
  class BePrime
    def matches?
      Prime.prime?(yield)
    end
  end
end

matcher = Matchi::BePrime.new
matcher.matches? { 42 } # => false

A Start with matcher:

module Matchi
  class StartWith
    attr_reader :expected

    def initialize(expected)
      @expected = expected
    end

    def matches?
      Regexp.new(/\A#{expected}/).match?(yield)
    end
  end
end

matcher = Matchi::StartWith.new("foo")
matcher.matches? { "foobar" } # => true

Contact

Versioning

Matchi follows Semantic Versioning 2.0.

License

The gem is available as open source under the terms of the MIT License.


This project is sponsored by:
Sashite