Rspec: „array.should == another_array”, ale bez obawy o porządek

235

Często chcę porównywać tablice i upewnić się, że zawierają te same elementy, w dowolnej kolejności. Czy istnieje zwięzły sposób na zrobienie tego w RSpec?

Oto metody, które są niedopuszczalne:

#to_set

Na przykład:

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

lub

array.to_set.should == another_array.to_set

Nie udaje się to, gdy tablice zawierają zduplikowane elementy.

#sort

Na przykład:

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

lub

array.sort.should == another_array.sort

Nie powiedzie się to, gdy elementy tablic nie zostaną zaimplementowane #<=>

nicholaides
źródło
7
Nie do smartassa, ale do porównywania to_seti sizefaktycznie nie robi tego, co chcesz. Np. [A, b, b] pasuje do [a, a, b]. Twoje zdrowie!
Jo Liss,
3
Dla tych, którzy natknęli się tutaj, zastanawiając się nad odwrotnością: porządek powinien być taki sam . Użyj eqdopasowywania, np.expect([1, 2]).to_not eq([2, 1])
Dennis

Odpowiedzi:

263

Próbować array.should =~ another_array

Najlepsza dokumentacja na ten temat, którą mogę znaleźć, to sam kod, który jest tutaj .

x1a4
źródło
To nie uwzględnia kolejności, więc nie jest to akceptowalna odpowiedź, prawda? Cytat z docs : Passes if actual contains all of the expected regardless of order..
Joshua Muheim
16
Tytuł tego postu: „Rspec:„ array.should == another_array ”, ale bez obawy o zamówienie”
x1a4
3
Jest to teraz oficjalnie udokumentowane w ramach dopasowań operatorów
Kelvin,
7
Jeśli używasz nowej składni „expect” znalezionej w rspec 3.0, zapoznaj się z odpowiedzią @JoshKovach.
clozach
46
Składnia Rspec 3.0 jest dostępna expect([1, 2, 3]).to match_array([2, 1, 3]): stackoverflow.com/a/19436763/33226
Gavin Miller
238

Od wersji RSpec 2.11 możesz także używać match_array.

array.should match_array(another_array)

Co może być bardziej czytelne w niektórych przypadkach.

[1, 2, 3].should =~ [2, 3, 1]
# vs
[1, 2, 3].should match_array([2, 3, 1])
Valentin Nemcev
źródło
8
tak, właśnie uaktualniono do szyn 4 i = ~ przestał działać tam, gdzie match_array działa dobrze, dzięki!
opsb
2
Nie wiem, czy to jest bardziej czytelne. Teraz brzmi, jakby to miało być dokładne dopasowanie, ale tak nie jest. Poprzedni squiggle był na tyle niejasny, że nic nie znaczył dla tablicy, więc nie miałem wstępnego przekonania. Może to tylko ja.
Trejkaz
1
Jeśli chodzi o „dokładne”, zawsze masz eq(), więc myślę, że match_array()jest dla mnie wystarczająco niejasny.
awendt
To nie działa dla mnie na listach uporządkowanych. Uważa, że ​​listy, które mają te same elementy w innej kolejności, są takie same. :-(
djangofan
FWIW match_arrayto pseudonim contain_exactly( dokumentacja )
Ruy Diaz
136

Stwierdziłem, =~że jest nieprzewidywalny i zawiodła bez wyraźnego powodu. Po wersji 2.14 prawdopodobnie powinieneś użyć

expect([1, 2, 3]).to match_array([2, 3, 1])
Josh Kovach
źródło
17
Również ważne przeszłość 3.0: expect([1, 2, 3]).to contain_exactly(2, 3, 1). relishapp.com/rspec/rspec-expectations/v/3-0/docs/…
clozach
13

Użyj match_array, która przyjmuje inną tablicę jako argument, lub contain_exactlyktóra bierze każdy element jako osobny argument i czasami jest przydatna dla czytelności. ( dokumenty )

Przykłady:

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

lub

expect([1, 2, 3]).to contain_exactly 3, 2, 1
nicholaides
źródło
3

W przypadku RSpec 3 użyj contain_exactly:

Zobacz https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcher, aby uzyskać szczegółowe informacje, ale oto fragment:

Match_exactly matcher zapewnia sposób testowania tablic względem siebie w sposób, który nie uwzględnia różnic w kolejności między rzeczywistą a oczekiwaną tablicą. Na przykład:

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

Jak zauważyli inni, jeśli chcesz twierdzić coś przeciwnego, że tablice powinny pasować zarówno do treści, jak i kolejności, użyj eq:

    expect([1, 2, 3]).to    eq([1, 2, 3]) # pass
    expect([1, 2, 3]).to    eq([2, 3, 1]) # fail
Tim Diggins
źródło
1

niezbyt dobrze udokumentowane, ale i tak dodałem linki:

Rspec3 docs

expect(actual).to eq(expected)


Rspec2 docs

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

Blair Anderson
źródło
11
Oba oczekują (rzeczywiste) .to eq (oczekiwane) i oczekują (rzeczywiste) .to match_array (oczekiwane) działają w rspec3, ale robią różne rzeczy. #match_array ignoruje kolejność, podczas gdy #eq nie.
gucki
1
To nie odpowiada na pytanie, ponieważ OP konkretnie poprosił o zignorowanie zamówienia.
NobodysNightmare
Tak! To zadziałało dla mnie. Porównanie kończy się niepowodzeniem, jeśli kolejność elementów nie jest taka sama. Dziękuję Ci! Mam na myśli .to eqmetodę, a nie match_array.
djangofan,