Rspec: "array.should == another_array", aber ohne Rücksicht auf die Reihenfolge


235

Ich möchte oft Arrays vergleichen und sicherstellen, dass sie dieselben Elemente in beliebiger Reihenfolge enthalten. Gibt es eine prägnante Möglichkeit, dies in RSpec zu tun?

Hier sind Methoden, die nicht akzeptabel sind:

#to_set

Beispielsweise:

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

oder

array.to_set.should == another_array.to_set

Dies schlägt fehl, wenn die Arrays doppelte Elemente enthalten.

#sort

Beispielsweise:

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

oder

array.sort.should == another_array.sort

Dies schlägt fehl, wenn die Arrays-Elemente nicht implementiert werden #<=>


7
Nicht zu schlau, sondern zu vergleichen to_setund sizetatsächlich nicht zu tun, was Sie wollen. ZB würde [a, b, b] mit [a, a, b] übereinstimmen. Prost!
Jo Liss

3
Für diejenigen, die hier gestolpert sind und sich das Gegenteil gefragt haben: Die Reihenfolge sollte dieselbe sein . Verwenden Sie den eqMatcher, zBexpect([1, 2]).to_not eq([2, 1])
Dennis

Antworten:


263

Versuchen array.should =~ another_array

Die beste Dokumentation dazu ist der Code selbst, der hier ist .


Dies berücksichtigt nicht die Reihenfolge, daher ist dies keine akzeptable Antwort, oder? Zitat aus den Dokumenten : Passes if actual contains all of the expected regardless of order..
Joshua Muheim

16
Titel dieses Beitrags: "Rspec:" array.should == another_array ", aber ohne Rücksicht auf die Bestellung"
x1a4

3
Dies ist jetzt offiziell unter Operator Matchers
Kelvin

7
Wenn Sie die neue "Expect" -Syntax in rspec 3.0 verwenden, lesen Sie die Antwort von @JoshKovach.
Clozach

46
Rspec 3.0 Syntax ist zu expect([1, 2, 3]).to match_array([2, 1, 3])sehen: stackoverflow.com/a/19436763/33226
Gavin Miller

238

Seit RSpec 2.11 können Sie auch verwenden match_array.

array.should match_array(another_array)

Was in einigen Fällen besser lesbar sein könnte.

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

8
yup, habe gerade auf Rails 4 aktualisiert und = ~ hat aufgehört zu arbeiten, wo match_array gut funktioniert, danke!
opsb

2
Ich weiß nicht, ob das besser lesbar ist. Jetzt liest es sich so, als ob es genau übereinstimmen sollte, aber es ist nicht so. Das vorherige Kringeln war vage genug, um für ein Array nichts zu bedeuten, also hatte ich nicht das Vorurteil. Vielleicht bin ich es nur.
Trejkaz

1
Für "genau" haben Sie immer eq(), also denke ich, match_array()ist vage genug für mich.
Awendt

Bei geordneten Listen funktioniert das bei mir nicht. Es glaubt, dass Listen, die dieselben Elemente in einer anderen Reihenfolge haben, gleich sind. :-(
Djangofan

FWIW match_arrayist ein Alias ​​für contain_exactly( Dokumentation )
Ruy Diaz


13

Verwenden Sie match_array, das ein anderes Array als Argument verwendet oder contain_exactlyjedes Element als separates Argument verwendet und manchmal für die Lesbarkeit hilfreich ist. ( docs )

Beispiele:

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

oder

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

3

Für RSpec 3 verwenden Sie contain_exactly:

Weitere Informationen finden Sie unter https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcher. Hier ist jedoch ein Auszug:

Der Matcher "include_exactly" bietet eine Möglichkeit, Arrays so gegeneinander zu testen, dass Unterschiede in der Reihenfolge zwischen dem tatsächlichen und dem erwarteten Array nicht berücksichtigt werden. Beispielsweise:

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

Wie andere darauf hingewiesen haben, sollten Sie, wenn Sie das Gegenteil behaupten möchten, dass die Arrays sowohl dem Inhalt als auch der Reihenfolge entsprechen sollten, verwenden eq, dh:

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

1

nicht sehr gut dokumentiert, aber ich habe trotzdem Links hinzugefügt:

Rspec3- Dokumente

expect(actual).to eq(expected)


Rspec2- Dokumente

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


11
Beide erwarten (tatsächlich) .to eq (erwartet) und erwarten (tatsächlich) .to match_array (erwartet) arbeiten in rspec3, aber sie machen verschiedene Dinge. #match_array ignoriert die Reihenfolge, #eq nicht.
Gucki

1
Dies beantwortet die Frage nicht, da das OP ausdrücklich darum gebeten hat, die Bestellung zu ignorieren.
NobodysNightmare

Ja! Das hat bei mir funktioniert. Ein Vergleich, der fehlschlägt, wenn die Reihenfolge der Elemente nicht identisch ist. Danke dir! Ich beziehe mich auf die .to eqMethode, nicht auf die match_array.
Djangofan
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.