Rspec:「array.should == another_array」ですが、順序は関係ありません


235

配列を比較して、同じ要素が任意の順序で含まれていることを確認したいことがよくあります。RSpecでこれを行う簡潔な方法はありますか?

許可されない方法は次のとおりです。

#to_set

例えば:

expect(array.to_set).to eq another_array.to_set

または

array.to_set.should == another_array.to_set

配列に重複したアイテムが含まれている場合、これは失敗します。

#sort

例えば:

expect(array.sort).to eq another_array.sort

または

array.sort.should == another_array.sort

配列要素が実装されていない場合、これは失敗します #<=>


7
smartassにではなく、比較するto_setと、size実際には期待どおりの結果が得られません。たとえば、[a、b、b]は[a、a、b]と一致します。乾杯!
Jo Liss、2011年

3
ここでつまずいた人のために、反対のことを考えています。順序は同じである必要があります。使用eq例マッチャー、expect([1, 2]).to_not eq([2, 1])
デニス・

回答:


263

試す array.should =~ another_array

これについて私が見つけることができる最良のドキュメントは、コード自体です(ここにあります)


これは注文を考慮に入れていないので、これは許容できる答えではありませんか?ドキュメントから引用:Passes if actual contains all of the expected regardless of order.
Joshua Muheim 2013年

16
この投稿のタイトル:「Rspec:「array.should == another_array」が順序を気にしない」
x1a4


7
rspec 3.0にある新しい "expect"構文を使用している場合は、@ JoshKovachからの回答を参照してください。
clozach 14

46
Rspec 3.0の構文は次のとおりですexpect([1, 2, 3]).to match_array([2, 1, 3])stackoverflow.com/a/19436763/33226
Gavin Miller

238

RSpec 2.11以降では、も使用できますmatch_array

array.should match_array(another_array)

これは、場合によっては読みやすくなります。

[1, 2, 3].should =~ [2, 3, 1]
# vs
[1, 2, 3].should match_array([2, 3, 1])

8
うん、rails 4にアップグレードしたばかりで、=〜はmatch_arrayが正常に機能する場所で機能しなくなりました。ありがとうございます!
opsb 2013

2
それがもっと読みやすいなら、私は知らない。完全に一致しているはずですが、そうではありません。以前の波線は、配列に対して何も意味しないほど漠然としていたので、私は先入観を持っていませんでした。多分それは私だけです。
Trejkaz 14年

1
「完全」の場合、常にがeq()あるのでmatch_array()、私にとっては漠然としていると思います。
awendt 2014

これは、順序付きリストでは機能しません。同じ項目が異なる順序であるリストは同じであると考えています。:-(
djangofan 2016

FWIWはmatch_arrayエイリアスですcontain_exactlyドキュメント
ルイディアス


13

match_array別の配列を引数として使用する、またはcontain_exactly各要素を個別の引数として使用するを使用します。これは、読みやすさのために役立つ場合があります。(ドキュメント

例:

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

または

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

3

RSpec 3を使用する場合contain_exactly

詳細については、https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcherを参照してください。ただし、抜粋は次のとおりです。

contains_exactlyマッチャーは、実際の配列と期待される配列の順序の違いを無視する方法で、配列を相互にテストする方法を提供します。例えば:

    expect([1, 2, 3]).to    contain_exactly(2, 3, 1) # pass
    expect([:a, :c, :b]).to contain_exactly(:a, :c ) # fail

他の人が指摘したように、反対を主張したい場合は、配列が内容と順序の両方に一致する必要があることを確認してから、を使用してくださいeq

    expect([1, 2, 3]).to    eq([1, 2, 3]) # pass
    expect([1, 2, 3]).to    eq([2, 3, 1]) # fail

1

十分に文書化されていませんが、とにかくリンクを追加しました:

Rspec3 ドキュメント

expect(actual).to eq(expected)


Rspec2 ドキュメント

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


11
expect(actual).to eq(expected)とexpect(actual).to match_array(expected)はどちらもrspec3で機能しますが、動作は異なります。#match_arrayは順序を無視しますが、#eqはしません。
gucki

1
OPは特に注文を無視するように要求したので、これは質問に答えません。
NobodysNightmare 2016年

はい!これでうまくいきました。要素の順序が同じでない場合に失敗する比較。ありがとうございました!.to eqメソッドではなく、を参照しmatch_arrayます。
djangofan 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.