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

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

16
ชื่อของโพสต์นี้: "Rspec:" array.should == another_array "แต่ไม่ต้องกังวลเกี่ยวกับคำสั่งซื้อ"
x1a4

3
ตอนนี้มีการบันทึกอย่างเป็นทางการภายใต้ผู้จับคู่โอเปอเรเตอร์
เคลวิน

7
หากคุณกำลังใช้ไวยากรณ์ "คาดหวัง" ใหม่ที่พบใน rspec 3.0 ดูคำตอบจาก @JoshKovach
clozach

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
yup เพิ่งอัพเกรดเป็น rails 4 และ = ~ หยุดทำงานที่ match_array ทำงานได้ดีขอบคุณ!
opsb

2
ฉันไม่รู้ว่าถ้าอ่านได้มากกว่านี้ ตอนนี้มันอ่านแล้วว่ามันควรจะเป็นการแข่งขันที่แน่นอน แต่มันไม่ใช่ Squiggle ก่อนหน้านั้นคลุมเครือมากพอที่จะไม่มีความหมายอะไรกับอาเรย์ดังนั้นฉันจึงไม่มีความคิด อาจจะเป็นเพียงฉัน
Trejkaz

1
สำหรับ "แน่นอน" คุณมีอยู่เสมอeq()ดังนั้นฉันเดาว่าmatch_array()คลุมเครือสำหรับฉัน
ประกาศใน

สิ่งนี้ใช้ไม่ได้สำหรับรายการสั่งซื้อ มันคิดว่ารายการที่มีรายการเดียวกันในลำดับที่แตกต่างกันเหมือนกัน :-(
djangofan

FWIW match_arrayเป็นนามแฝงสำหรับcontain_exactly( เอกสาร )
Ruy Diaz

136

ฉันพบว่า=~ไม่แน่นอนและล้มเหลวโดยไม่มีเหตุผลที่ชัดเจน ที่ผ่านมา 2.14 คุณน่าจะใช้

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

17
นอกจากนี้ที่ผ่านมาที่ถูกต้อง expect([1, 2, 3]).to contain_exactly(2, 3, 1)3.0: relishapp.com/rspec/rspec-expectations/v/3-0/docs/ …
clozach

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สำหรับรายละเอียด แต่นี่เป็นสารสกัด:

match_exactly matcher มีวิธีการทดสอบอาร์เรย์ซึ่งกันและกันโดยไม่คำนึงถึงความแตกต่างในการเรียงลำดับระหว่างอาร์เรย์จริงกับอาร์เรย์ที่คาดไว้ ตัวอย่างเช่น:

    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
ทั้งคาดหวัง (จริง) .to eq (คาดว่า) และคาดหวัง (จริง) .to match_array (คาดว่า) ทำงานใน rspec3 แต่พวกเขากำลังทำสิ่งที่แตกต่างกัน #match_array ละเว้นการสั่งซื้อในขณะที่ #eq ไม่ทำเช่นนั้น
gucki

1
สิ่งนี้ไม่ตอบคำถามเนื่องจาก OP ขอให้เพิกเฉยต่อคำสั่งซื้อโดยเฉพาะ
NobodysNightmare

ใช่ สิ่งนี้ใช้ได้สำหรับฉัน การเปรียบเทียบที่ล้มเหลวหากลำดับขององค์ประกอบไม่เหมือนกัน ขอบคุณ! ผมหมายถึงวิธีการไม่ได้.to eq match_array
djangofan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.