Rspec: "array.should == another_array" ma senza preoccupazioni per l'ordine


235

Vorrei spesso confrontare le matrici e assicurarmi che contengano gli stessi elementi, in qualsiasi ordine. C'è un modo conciso per farlo in RSpec?

Ecco alcuni metodi che non sono accettabili:

#to_set

Per esempio:

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

o

array.to_set.should == another_array.to_set

Ciò non riesce quando le matrici contengono elementi duplicati.

#sort

Per esempio:

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

o

array.sort.should == another_array.sort

Questo non riesce quando gli elementi degli array non vengono implementati #<=>


7
Non per smartass, ma il confronto to_sete in sizerealtà non fa quello che vuoi. Ad esempio [a, b, b] corrisponderebbe a [a, a, b]. Saluti!
Jo Liss,

3
Per coloro che sono inciampati qui chiedendosi il contrario: l' ordine dovrebbe essere lo stesso . Usa il eqmatcher, ad esexpect([1, 2]).to_not eq([2, 1])
Dennis

Risposte:


263

Provare array.should =~ another_array

La migliore documentazione su questo che posso trovare è il codice stesso, che è qui .


Questo non tiene conto dell'ordine, quindi questa non è una risposta accettabile, vero? Citazione dal docs : Passes if actual contains all of the expected regardless of order..
Joshua Muheim,

16
Titolo di questo post: "Rspec:" array.should == another_array "ma senza preoccupazioni per l'ordine"
x1a4

3
Questo è ora ufficialmente documentato sotto gli operatori corrispondenti
Kelvin,

7
Se stai usando la nuova sintassi "prevede" trovata in rspec 3.0, vedi la risposta di @JoshKovach.
clozach,

46
La sintassi di Rspec 3.0 è expect([1, 2, 3]).to match_array([2, 1, 3])visibile: stackoverflow.com/a/19436763/33226
Gavin Miller,

238

Da RSpec 2.11 puoi anche usare match_array.

array.should match_array(another_array)

Quale potrebbe essere più leggibile in alcuni casi.

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

8
Sì, appena aggiornato a Rails 4 e = ~ ha smesso di funzionare dove match_array funziona bene, grazie!
opsb,

2
Non so se sia più leggibile. Ora sembra che dovrebbe essere una corrispondenza esatta, ma non lo è. Lo squiggle precedente era abbastanza vago da non significare nulla per un array, quindi non avevo il preconcetto. Forse sono solo io.
Trejkaz,

1
Per "esatto", lo hai sempre fatto eq(), quindi credo che match_array()sia abbastanza vago per me.
Awendt

Questo non funziona per me negli elenchi ordinati. Pensa che gli elenchi, che hanno gli stessi elementi in un ordine diverso, siano gli stessi. :-(
djangofan,

FWIW match_arrayè un alias per contain_exactly( documentazione )
Ruy Diaz,


13

Usa match_array, che accetta un altro array come argomento oppure contain_exactlyche accetta ogni elemento come argomento separato ed è talvolta utile per la leggibilità. ( documenti )

Esempi:

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

o

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

3

Per RSpec 3 utilizzare contain_exactly:

Vedi https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcher per i dettagli, ma ecco un estratto:

La funzione match_exactly matcher fornisce un modo per testare gli array l'uno contro l'altro in modo da ignorare le differenze nell'ordinamento tra l'array effettivo e quello previsto. Per esempio:

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

Come altri hanno sottolineato, se si vuole affermare il contrario, che gli array devono corrispondere sia al contenuto che all'ordine, quindi utilizzare eq, ad es .:

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

1

non documentato molto bene ma ho aggiunto comunque dei collegamenti:

Documenti Rspec3

expect(actual).to eq(expected)


Documenti Rspec2

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


11
Entrambi si aspettano (effettivo) .to eq (atteso) e si aspettano (effettivo) .to match_array (previsto) lavorare in rspec3, ma stanno facendo cose diverse. #match_array ignora l'ordinamento, mentre #eq no.
Gucki,

1
Ciò non risponde alla domanda, poiché il PO ha chiesto espressamente di ignorare l'ordine.
NobodysNightmare,

Sì! Questo ha funzionato per me. Un confronto che fallisce se l'ordine degli elementi non è lo stesso. Grazie! Mi riferisco al .to eqmetodo, non al match_array.
Djangofan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.