🧭

RSpec 配列に使えるマッチャ match_array, contain_exactly, eq, include 違い

2023/03/28に公開

(雑なタイトルになってしまったが・・・🙏)

match_array

  • マッチャには配列を渡す
  • 並び順が違ってもテストは通る
expect([1, 2]).to match_array([1, 2])
expect([1, 2]).to match_array([2, 1])

これは通らない。

expect([1, 2, 3]).to match_array([1])

contain_exactly

  • マッチャには要素を渡す
  • 並び順が違ってもテストは通る
  • よく使う
# テストは通る
expect([1, 2]).to contain_exactly(1, 2)
expect([1, 2]).to contain_exactly(2, 1)

これは通らない。

expect([1, 2, 3]).to contain_exactly(1)

RSpec :: RuboCop Docsでは、配列の要素を確かめるならmatch_arrayではなくcontain_exactlyを使うように推奨されている。

# bad
it { is_expected.to match_array([content1, content2]) }

# good
it { is_expected.to contain_exactly(content1, content2) }

配列の要素と並び順もテストしたい場合: eq

  • 配列の要素に加えて、並び順を担保したいならeqを使う
  • Array専用メソッドではない
expect([1, 2]).to eq [1, 2]

以下のテストは配列の要素は合っているが、並び順が違うので落ちる。

expect([1, 2]).to eq [2, 1]

テスト結果↓

Failure/Error: expect([1, 2]).to eq [2, 1]     
     expected: [2, 1]
     got: [1, 2]

ある特定の要素が配列に含まれてればいい場合: include

  • どれか1つでも同じ要素があればいい場合、includeが使える
  • 並び順は関係しない
  • Array専用メソッドではない
expect([1, 2]).to include 1

まとめ

  • match_array:並び順は関係なく、要素がすべて含まれてることを担保したい(マッチャには配列を渡す)
  • contain_exactly:並び順は関係なく、要素がすべて含まれてることを担保したい(マッチャには要素を渡す)
  • eq:要素と並び順を担保したい
  • include:どれか1つの要素が含まれてればいい

個人的には、contain_exactly, eq, includeをよく使う印象がある。

余談だが、Rubyでrspecを動かしたい場合はrequire 'rspec'をして、rspec <filename>.rbコマンドでテストを実行できる。

require 'rspec'

RSpec.describe 'Array Matchers' do
  it 'match array' do
    expect([1, 2]).to match_array([1, 2])
  end
end

gem install rspecを忘れずに

参考: RSpecのドキュメント
RSpec: Behaviour Driven Development for Ruby

Discussion