Rspec: “array.should == another_array” tetapi tanpa memperhatikan pesanan


235

Saya sering ingin membandingkan array dan memastikan bahwa mereka mengandung elemen yang sama, dalam urutan apa pun. Apakah ada cara ringkas untuk melakukan ini di RSpec?

Berikut adalah metode yang tidak dapat diterima:

#to_set

Sebagai contoh:

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

atau

array.to_set.should == another_array.to_set

Ini gagal ketika array berisi item duplikat.

#sort

Sebagai contoh:

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

atau

array.sort.should == another_array.sort

Ini gagal ketika elemen array tidak diimplementasikan #<=>


7
Bukan untuk sok pintar, tetapi membandingkan to_setdan sizesebenarnya tidak melakukan apa yang Anda inginkan. Misalnya [a, b, b] akan cocok dengan [a, a, b]. Bersulang!
Jo Liss

3
Bagi mereka yang tersandung di sini bertanya-tanya sebaliknya: urutannya harus sama . Gunakan eqpencocokan, misalnyaexpect([1, 2]).to_not eq([2, 1])
Dennis

Jawaban:


263

Mencoba array.should =~ another_array

Dokumentasi terbaik tentang ini dapat saya temukan adalah kode itu sendiri, yang ada di sini .


Ini tidak memperhitungkan pesanan, jadi ini bukan jawaban yang dapat diterima, bukan? Mengutip dari docs : Passes if actual contains all of the expected regardless of order..
Joshua Muheim

16
Judul posting ini: "Rspec:" array.should == another_array "tetapi tanpa memperhatikan pesanan"
x1a4

3
Ini sekarang secara resmi didokumentasikan di bawah pencocokan operator
Kelvin

7
Jika Anda menggunakan sintaks "harapan" baru yang ditemukan di rspec 3.0, lihat jawabannya dari @JoshKovach.
clozach

46
Sintaks Rspec 3.0 dapat expect([1, 2, 3]).to match_array([2, 1, 3])dilihat: stackoverflow.com/a/19436763/33226
Gavin Miller

238

Karena RSpec 2.11 Anda juga dapat menggunakan match_array.

array.should match_array(another_array)

Yang bisa lebih mudah dibaca dalam beberapa kasus.

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

8
ya, baru saja ditingkatkan ke rails 4 dan = ~ berhenti bekerja di mana match_array berfungsi dengan baik, terima kasih!
opsb

2
Saya tidak tahu apakah itu lebih mudah dibaca. Sekarang bunyinya seperti itu harus sama persis, tapi tidak. Keributan sebelumnya cukup samar untuk tidak berarti apa-apa untuk sebuah array, jadi saya tidak memiliki prasangka. Mungkin hanya aku.
Trejkaz

1
Untuk "tepat", Anda selalu punya eq(), jadi saya kira match_array()cukup samar untuk saya.
awendt

Ini tidak berfungsi untuk saya pada daftar yang dipesan. Itu berpikir daftar, yang memiliki item yang sama dalam urutan berbeda, adalah sama. :-(
Djangofan

FWIW match_arrayadalah alias untuk contain_exactly( dokumentasi )
Ruy Diaz


13

Gunakan match_array, yang menggunakan array lain sebagai argumen, atau contain_exactly, yang menggunakan setiap elemen sebagai argumen terpisah, dan terkadang berguna untuk keterbacaan. ( docs )

Contoh:

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

atau

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

3

Untuk RSpec 3 gunakan contain_exactly:

Lihat https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/contain-exactly-matcher untuk detailnya, tapi inilah kutipannya:

Matcher content_exactly menyediakan cara untuk menguji array terhadap satu sama lain dengan cara yang mengabaikan perbedaan dalam pemesanan antara array aktual dan yang diharapkan. Sebagai contoh:

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

Seperti yang telah ditunjukkan orang lain, jika Anda ingin menegaskan sebaliknya, bahwa array harus cocok dengan konten dan pesanan, kemudian gunakan eq, yaitu .:

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

1

tidak didokumentasikan dengan baik tetapi saya menambahkan tautan:

Dokumen Rspec3

expect(actual).to eq(expected)


Rspec2 docs

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


11
Keduanya mengharapkan (aktual). Hingga eq (diharapkan) dan mengharapkan (aktual). Untuk match_array (diharapkan) bekerja di rspec3, tetapi mereka melakukan hal yang berbeda. #match_array mengabaikan urutan, sedangkan #eq tidak.
gucki

1
Ini tidak menjawab pertanyaan, karena OP secara khusus diminta untuk mengabaikan pesanan.
NobodysNightmare

Iya! Ini berhasil untuk saya. Perbandingan yang gagal jika urutan elemen tidak sama. Terima kasih! Saya merujuk pada .to eqmetode, bukan match_array.
Djangofan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.