たばりばりスタイル

たばりばりスタイル

バリバリバリ⚡︎

RSpecのCustom Matcherをカジュアルに追加している

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 を使っているところがなかったので、実際どうなんだろう。

以上です。