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


86

我知道在水豚,您可以执行以下操作:

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驱动程序和RSpec。


众所周知,在capybara中实现了“ page.should have_css(“ ol li”,:count => 2)“。我认为它在范围内非常有用:inside(“ ol.users-list”)做page.should have_css('li',:count => 3)end
rafaelkin

@rafaelkin,只是为了澄清:水豚现在是否报告例如元素计数不匹配的更多细节?我已经有一段时间没有关注capybara了,但是当我提出问题时的问题是关于错误消息的格式,但那page.should have_css("ol li", :count => 2)还没有实现。
merryprankster

乡亲们,我觉得当前接受的答案(=我自己的答案)不再是最好的,但是没有时间(不再与Ruby一起工作)来评估哪种建议的解决方案是最好的。我将接受的答案更改为Richard的答案,仅因为它包括解决原始问题的断言输出。
merryprankster

Answers:



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

现在就成功了,我将研究制作这部分的水豚。



14

我认为以下内容比较简单,可以提供清晰的输出,并且不需要自定义匹配器。

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

然后在错误时输出:

      expected: 2
       got: 3

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

9
这不会等待期望实现,例如,当仍有待处理的ajax请求时。
Clemens Helm 2014年

9

编辑:正如@ThomasWalpole所指出的那样,使用all会禁用Capybara的等待/重试功能,因此上述@pandaPower的答案要好得多。

这个怎么样?

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

2
这完全击败了水豚等待/重试,绝不应该作为推荐的解决方案。
Thomas Walpole

@ThomasWalpole我不确定您在说什么。在另一元素内寻找元素如何与在水豚中等待/重试有什么关系?
康斯坦丁·梅林

2
@ConstantMeiring不是within,它正在调用禁用等待/重试.count的结果all。通过调用count结果all(一个空的“数组”是有效的返回值),您可以转换为整数并进行比较。如果该比较失败,则期望将失败。相反,如果将count选项传递给Capybara的匹配器之一,则capybara将等待/重试查找指定的选择器,直到count选项匹配(或Capybara.default_max_wait_time过期)。
Thomas Walpole

4

以下是水豚推荐的(9/2/2013)最佳实践(来源):

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


-4

@pandaPower的答案非常好,但是语法对我来说略有不同:

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

5
使用哈希火箭不能视为“不同语法”。
2014年

2
我不是ruby开发人员,也没有意识到这两种语法是等效的。TBH我不确定是否需要投票。这是一个有效的选择。对于那些不是Ruby背景的人来说,这似乎并不明显。不是给我的
尼克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.