Tbpgr Blog

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

RSpec | カスタムマッチャーを作成する

概要

カスタムマッチャーを作成する

内容

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

仕様

あるクラスのフィールドに対して、指定したマップ内のキーのフィールドが
バリューの値を持っているか全比較し、全て保持していればマッチ成功とする。
主に登録処理、編集処理後のレコード内容の確認を想定。
メソッド名はhave_attributes。

カスタムマッチャークラス

require "yaml"

module CustomMatchers
  class HaveAttributes
    def initialize(expected)
      @expected = expected
    end

    def matches?(actual)
      @actual = actual
      @expected.each do |k, v|
        unless actual.method(k).call == v
          @error_actual = "#{k} = #{actual.method(k).call}"
          @error_expected = "#{k} = #{v}"
          return false 
        end
      end
      true
    end

    def description
      "have all expected attributes values(#{@expected})."
    end

    def failure_message
      <<-MSG
      actual
        #{@error_actual}
      expected
        #{@error_expected}
      MSG
    end

    def negative_failure_message
      <<-MSG
      actual
        #{@actual.to_yaml}
      expected
        #{@expected.to_yaml}
      MSG
    end
  end

  def have_attributes(expected)
    HaveAttributes.new(expected)
  end
end

spec_helper.rb

RSpec.configure do |config|
  config.include CustomMatchers
end

実際に呼び出す

プロダクトコード
# encoding: utf-8
require "pp"

class Hoge
  attr_accessor :hoge, :hige, :hage
  def initialize
    @hoge, @hige, @hage = "hoge", "hige", "hage"
  end
end
テストコード
# encoding: utf-8
require_relative "spec_helper"
require_relative "../lib/hoge"

describe "test" do
  it "test" do
    hoge = Hoge.new
    expect(hoge).to have_attributes(:hoge => "hoge", :hige => "hige", :hage => "hage")
  end
end
実行結果
$rspec hoge_spec.rb
Run options: include {:focus=>true}

All examples were filtered out; ignoring {:focus=>true}
.

Finished in 0.001 seconds
1 example, 0 failures
実行結果(期待値を変更してわざと失敗させます)
$rspec hoge_spec.rb
Run options: include {:focus=>true}

All examples were filtered out; ignoring {:focus=>true}
F

Failures:

  1) test test
     Failure/Error: expect(hoge).to have_attributes(:hoge => "hoge", :hige => "hige", :hage => "hage!!")
             actual
               hage = hage
             expected
               hage = hage!!
     # ./hoge_spec.rb:8:in `block (2 levels) in <top (required)>'

Finished in 0.001 seconds
1 example, 1 failure

Failed examples:

rspec ./hoge_spec.rb:6 # test test