RSpecのカスタムマッチャの作り方をいろいろ調べたのでメモ📝
作り方
RSpec::Matchers.define
を使う
カジュアルな追加方法としてRSpec::Matchers.define
で追加する方法があります。
以下の公式ドキュメントの通りにRSpec::Matchers.define
の引数にmatcher名を渡してdefineのブロック引数に期待する値、matchの引数に実際の値を指定してあげれば良いようです📝
You can create such a matcher like so:
RSpec::Matchers.define :be_in_zone do |zone| match do |player| player.in_zone?(zone) end end
Module: RSpec::Matchers — Documentation for rspec-expectations (3.12.3)
実際に以下のような単純に同一の値になるか確認するカスタムマッチャを追加して、
RSpec::Matchers.define :my_eqdo |expected| match do |actual| expected == actual endend
以下のようなテストを流すと、
describe 'test'do it 'check my_eq'do expect(true).to my_eq(false) endend
以下のようにテスト結果が表示されます🙌
Failures: 1) test check my_eq Failure/Error: expect(true).to my_eq(false) expected true to my eq false
moduleで定義する
RSpec::Matchers.define
を使うとカジュアルに追加できますが実際にマッチャのテストコードを書きたいといった場合にはmoduleとして定義するとやりやすいようです。
以下のような検証用のロジックをもつclassとマッチャの呼び出すテストコード内で呼び出す名称のメソッドを持つmoduleを定義してあげて、
moduleMyEqMatcherclassMatcherdefinitialize(expected) @expected = expected enddefmatches?(_expected) @actual = actual @expected == @actualenddeffailure_message"#{@expected} expected, but got #{@actual}"endenddefmy_eq(expected) Matcher.new(expected) endend
以下の通りにconfig.include
でテストコード内で利用できるようにすることができます。
RSpec.configure do |config| config.include MyEqMatcherend
以下の通り実行するといい感じにカスタムマッチャーを使ってエラーになることが確認できます 🙌
describe 'test'do it 'check my_eq'do expect(true).to my_eq(false) endend
1) test check my_eq Failure/Error: expect(true).to my_eq(false) false expected, but got true
おわりに
RSpecのカスタムマッチャ、意外と簡単に追加できて便利ですね!!