Rails で開発、テスト (RSpec) していると、Custom Matcher を作りたくなるケースがあります。
例えば下記のようなケースです。
RSpec.describe User, type: :model do context 'Userのemailがnilの場合' do subject { build :user, email: nil } before { subject.valid? } # Userのemailがnilの場合にemailのエラーを持つか確認 it { expect(user.errors.has_key?(:name)).to eq true } # ワンライナー end end
# テストを実行 $ bundle exec rspec -fd User Userのemailがnilの場合 is expected to eq true
このテストだと出力でテスト内容が理解できませんし、テストの内容と出力にズレが生じています。(User の email が nil の場合に true が期待されているように見える
個人的にこの出力のされ方が好きではないため、expect の引数であれこれ記述しないようにしています。
このようなケースでは下記のように Custom Matcher を自作してテストをしています。
# Custom Matcher RSpec::Matchers.define :have_error do |expected| match do |actual| actual.errors.has_key? expected end description do "have an error in #{expected}" end end RSpec.describe User, type: :model do context 'Userのemailがnilの場合' do subject { build :user, email: nil } before { subject.valid? } it { is_expected.to have_error :email } end end
# テストを実行 $ bundle exec rspec -fd User Userのemailがnilの場合 is expected to have an error in email
上記の出力のように Custom Matcher を使うだけで、テスト内容が出力からある程度理解でき、テストの内容と出力で起こるズレを減らせます。
なので、既存の Matcher で it { is_expected.to matcher_name expected }
のように書けないテストには、カジュアルに Custom Matcher の追加を検討していくようにしています。
ただ、これまでの現場ではあまり Custom Matcher を使っているところがなかったので、実際どうなんだろう。
以上です。