Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

Ruby on Rails | Rails+MiniTestでカスタムマッチャーを作成する

概要

Rails+MiniTestでカスタムマッチャーを作成する

内容

Rails+MiniTestでカスタムマッチャーを作成します。

手順

Gemfileに下記を追加

gem "minitest-matchers", "~> 1.3.0"

サンプル

仕様

・任意のモデルの内容を検証する
・指定したハッシュのキーで、列の値を検証
・ハッシュで指定した全ての値が一致すれば検証成功
railsのpluginプロジェクトで、独自のカスタムマッチャが必要になったケースを想定

Gemfiles

下記を追加

gem "minitest-matchers", "~> 1.3.0"
lib/plugin_name/support/matchers/have_attributes.rb
require "minitest/matchers"
require "yaml"

# = カスタムマッチャ
module MyMatchers
  # = Modleの属性保持検証用カスタムマッチャ
  module HaveAttributes
    # = Modleの属性保持検証用カスタムマッチャ
    class Matcher
      # == 初期化
      # 
      # === params
      # actual:: 実値
      def initialize(actual)
        @actual = actual
      end

      # == Modleの属性保持検証実行
      # 
      # === params
      # expected:: 期待値
      def matches?(expected)
        @expected = expected
        @diffs = []
        ret = true
        @expected.each {|k, v|
          _actual = @actual.method(k).call
          unless _actual == v
            @diffs << {key: k, actual: _actual, expected: v}
            ret = false
          end
        }
        ret
      end

      # == 検証失敗時メッセージ(have_attributes用)
      def failure_message_for_should
        msg = []
        @diffs.each do |e|
          msg << "key=#{e[:key]}\n\tExpected=#{e[:expected]}\n\tActual=#{e[:actual]}\n"
        end
        msg.join("\n")
      end

      # == 検証失敗時メッセージ(not_have_attributes用)
      def failure_message_for_should_not
        msg=<<EOS
expected & actual all match.it must have at least 1-unmatch field.
Expected=#{@expected}
Actual=#{@actual.to_yaml}
EOS
      end
    end

    MiniTest::Unit::TestCase.register_matcher Matcher, :have_attributes
  end
end
test_helper.rb

下記を追記し、追加したカスタムマッチャをMini::Testに追加する。

# support/matcherにカスタムマッチャを配置した場合のrequire
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |support| require support}
class MiniTest::Spec
  include ::MyMatchers::HaveAttributes
end
利用時
# 肯定検証
assert_have_attributes(expected, actual)
# 否定検証
refute_have_attributes(expected, actual)