จะยืนยันจำนวนองค์ประกอบโดยใช้ Capybara ด้วยข้อความแสดงข้อผิดพลาดที่เหมาะสมได้อย่างไร


87

ฉันรู้ว่าใน Capybara คุณสามารถทำสิ่งนี้ได้:

page.should have_css("ol li", :count => 2)

อย่างไรก็ตามหากสมมติว่าหน้านั้นมีองค์ประกอบที่ตรงกันเพียงรายการเดียวข้อผิดพลาดนี้ไม่สามารถอธิบายได้มากนัก:

  1) initial page load shows greetings
 Failure/Error: page.should have_css("ol li", :count => 2)
 expected css "ol li" to return something

แทนที่จะเป็นข้อความแสดงข้อผิดพลาดที่ค่อนข้างคลุมเครือนี้มีวิธีการเขียนการยืนยันในลักษณะที่ผลลัพธ์ของข้อผิดพลาดจะเป็นเช่น 'เมื่อจับคู่' ol li ', คาดว่า: 2, พบ: 1' เห็นได้ชัดว่าฉันสามารถสร้างตรรกะที่กำหนดเองสำหรับพฤติกรรมดังกล่าวได้ - ฉันกำลังถามว่ามีวิธีทำ 'นอกกรอบ' หรือไม่?

สำหรับสิ่งที่คุ้มค่าฉันใช้ Selenium driver และ RSpec


เพื่อให้ผู้คนทราบว่า "page.should have_css (" ol li ",: count => 2)" ถูกนำไปใช้ในคาปิบารา ฉันคิดว่ามันใช้งานได้ดีกับขอบเขต: within ("ol.users-list") do page.should have_css ('li',: count => 3) end
rafaelkin

@rafaelkin เพียงเพื่อชี้แจง: ตอนนี้ Capybara รายงานเช่นการไม่ตรงกันในองค์ประกอบนับพร้อมรายละเอียดเพิ่มเติมหรือไม่? ฉันไม่ได้ติดตาม capybara มาระยะหนึ่งแล้ว แต่ปัญหาในตอนนั้นเมื่อฉันตั้งคำถามเกี่ยวกับรูปแบบของข้อความแสดงข้อผิดพลาดไม่ใช่ว่าpage.should have_css("ol li", :count => 2)จะยังไม่ได้ใช้งาน
merryprankster

เพื่อน ๆ ฉันรู้สึกว่าคำตอบที่ยอมรับในปัจจุบัน (= ของฉันเอง) ไม่ใช่คำตอบที่ดีที่สุดอีกต่อไป แต่ไม่มีเวลา (ไม่ได้ทำงานกับ Ruby อีกต่อไป) เพื่อประเมินว่าโซลูชันใดที่แนะนำดีที่สุด ฉันจะเปลี่ยนคำตอบที่ยอมรับเป็นของ Richard เพียงเพราะมันมีผลลัพธ์ของการยืนยันซึ่งจัดการกับปัญหาเดิม
merryprankster

คำตอบ:



22

เนื่องจากดูเหมือนว่าไม่มีการสนับสนุนนอกกรอบฉันจึงเขียนตัวจับคู่ที่กำหนดเองนี้:

RSpec::Matchers.define :match_exactly do |expected_match_count, selector|
    match do |context|
        matching = context.all(selector)
        @matched = matching.size
        @matched == expected_match_count
    end

    failure_message_for_should do
        "expected '#{selector}' to match exactly #{expected_match_count} elements, but matched #{@matched}"
    end

    failure_message_for_should_not do
        "expected '#{selector}' to NOT match exactly #{expected_match_count} elements, but it did"
    end
end

ตอนนี้คุณสามารถทำสิ่งต่างๆเช่น:

describe "initial page load", :type => :request do
    it "has 12 inputs" do
        visit "/"
        page.should match_exactly(12, "input")
    end
end

และรับผลลัพธ์เช่น:

  1) initial page load has 12 inputs
     Failure/Error: page.should match_exactly(12, "input")
       expected 'input' to match exactly 12 elements, but matched 13

มันเป็นเคล็ดลับสำหรับตอนนี้ฉันจะดูการสร้างส่วนนี้ของ Capybara


ดูเหมือนว่าการแก้ไขใน Capybara จะไม่ตรงไปตรงมา: github.com/jnicklas/capybara/issues/331
merryprankster

14

ฉันคิดว่าสิ่งต่อไปนี้ง่ายกว่าให้ผลลัพธ์ที่ค่อนข้างชัดเจนและไม่จำเป็นต้องมีตัวจับคู่แบบกำหนดเอง

page.all("ol li").count.should eql(2)

สิ่งนี้จะพิมพ์ออกมาเมื่อเกิดข้อผิดพลาด:

      expected: 2
       got: 3

  (compared using eql?)
  (RSpec::Expectations::ExpectationNotMetError)

9
สิ่งนี้ไม่รอให้ความคาดหวังเป็นจริงเช่นเมื่อยังคงมีคำขอ ajax ที่รอดำเนินการอยู่
Clemens Helm

9

แก้ไข:ตามที่ @ThomasWalpole ชี้ให้เห็นโดยใช้การallปิดใช้งานการรอ / ลองใหม่ของ Capybara ดังนั้นคำตอบข้างต้นโดย @pandaPower จึงดีกว่ามาก

แล้วเรื่องนี้ล่ะ?

  within('ol') do
    expect( all('.opportunity_title_wrap').count ).to eq(2)
  end

2
สิ่งนี้เอาชนะ Capybaras ที่รอ / ลองใหม่ได้อย่างสมบูรณ์และไม่ควรเป็นวิธีแก้ปัญหาที่แนะนำ
Thomas Walpole

@ThomasWalpole ฉันไม่แน่ใจว่าคุณกำลังพูดถึงอะไร การมองหาองค์ประกอบภายในองค์ประกอบอื่นจะสัมผัสกับการรอ / การลองใหม่ใน Capybara อย่างไร
Constant Meiring

2
@ConstantMeiring ไม่ใช่withinอย่างนั้นมันกำลังเรียกร้อง.countผลของการallปิดใช้งานการรอ / ลองใหม่ โดยการเรียกcountผลลัพธ์ของall(ซึ่ง "อาร์เรย์" ว่างเปล่าเป็นผลตอบแทนที่ถูกต้องสำหรับ) คุณจะแปลงเป็นจำนวนเต็มและเปรียบเทียบ หากการเปรียบเทียบนั้นล้มเหลวความคาดหวังก็ล้มเหลว หากคุณส่งตัวเลือก count ไปยังหนึ่งใน matchers ของ Capybara แทน capybara จะรอ / ลองค้นหาตัวเลือกที่ระบุอีกครั้งจนกว่าตัวเลือก count จะตรงกัน (หรือ Capybara.default_max_wait_time จะหมดอายุ)
Thomas Walpole

4

แนวทางปฏิบัติที่ดีที่สุดในปัจจุบัน (9/2/2013) ที่แนะนำโดย Capybara มีดังต่อไปนี้ (ที่มา ):

page.assert_selector('p#foo', :count => 4)


-4

คำตอบโดย @pandaPower นั้นดีมาก แต่ไวยากรณ์แตกต่างกันเล็กน้อยสำหรับฉัน:

expect(page).to have_selector('.views-row', :count => 30)

5
การใช้แฮชจรวดไม่ถือว่าเป็น "ไวยากรณ์ที่แตกต่างกัน"
premjg

2
ฉันไม่ใช่นักพัฒนา Ruby และไม่รู้ว่าไวยากรณ์ทั้งสองมีค่าเท่ากัน TBH ฉันไม่แน่ใจว่ามันรับประกันการลงคะแนน เป็นทางเลือกที่ถูกต้อง สำหรับผู้ที่ไม่ได้มาจากพื้นหลัง Ruby อาจดูเหมือนไม่ชัดเจน มันไม่ใช่สำหรับฉัน
Nick
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.