如何使用Capybara声明元素数量并带有正确的错误消息?

mer*_*ter 82 dsl rspec capybara

我知道在Capybara,你可以这样做:

page.should have_css("ol li", :count => 2)
Run Code Online (Sandbox Code Playgroud)

但是,假设该页面仅具有一个匹配元素,则该错误不是非常具有描述性:

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

而不是这个相当模糊的错误消息,有没有办法以这样的方式编写断言,即错误输出将类似于'匹配'ol li',期望:2,找到:1'.显然我可以自己为这样的行为制作一个自定义逻辑 - 我问有没有办法在开箱即用的情况下做到这一点?

对于它的价值,我使用的是Selenium驱动程序和RSpec.

小智 169

我更喜欢这个.

expect(page).to have_selector('input', count: 12)
Run Code Online (Sandbox Code Playgroud)

https://github.com/jnicklas/capybara/blob/415e2db70d3b19b46a4d3d0fe62f50400f9d2b61/spec/rspec/matchers_spec.rb

  • 也适用于`have_css`:`expect(page).to have_css('input',count:12)` (10认同)

mer*_*ter 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
Run Code Online (Sandbox Code Playgroud)

现在,您可以执行以下操作:

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

获得如下输出:

  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
Run Code Online (Sandbox Code Playgroud)

它现在可以解决这个问题,我将研究制作这部分Capybara.


Ric*_*ard 14

我认为以下更简单,输出相当清晰,无需自定义匹配器.

page.all("ol li").count.should eql(2)
Run Code Online (Sandbox Code Playgroud)

然后打印出错误:

      expected: 2
       got: 3

  (compared using eql?)
  (RSpec::Expectations::ExpectationNotMetError)
Run Code Online (Sandbox Code Playgroud)

  • 这并不等待期望成为现实,例如,当仍有未决的ajax请求时. (8认同)

Con*_*ing 9

编辑:正如@ThomasWalpole指出的,使用all禁用Capybara 的等待/重试,所以@pandaPower的答案要好得多.

这个怎么样?

  within('ol') do
    expect( all('.opportunity_title_wrap').count ).to eq(2)
  end
Run Code Online (Sandbox Code Playgroud)

  • 可爱的答案+1 (2认同)
  • 这完全打败了Capybaras等待/重试,绝不应该是推荐的解决方案. (2认同)
  • @ConstantMeiring它不是`within`,它在`all`的结果上调用`.count`来禁用等待/重试.通过对`all`的结果调用`count`(一个空的"数组"是一个有效的返回),你转换为一个整数并进行比较.如果该比较失败,则期望失败.如果您将计数选项传递给Capybara的匹配器之一,则capybara将等待/重试查找指定的选择器,直到count选项匹配(或Capybara.default_max_wait_time到期). (2认同)

acc*_*rad 5

目前(2013 年 9 月 2 日)Capybara 推荐的最佳实践如下(来源):

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