如何使用 Capybara 使用正确的错误消息断言元素数量?
Posted
技术标签:
【中文标题】如何使用 Capybara 使用正确的错误消息断言元素数量?【英文标题】:How to assert number of elements using Capybara with proper error message? 【发布时间】:2011-10-07 10:23:11 【问题描述】:我知道在 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 驱动程序和 RSpec。
【问题讨论】:
大家都知道,"page.should have_css("ol li", :count => 2)" 是在 capybara 中实现的。我认为它非常适用于范围:within("ol.users-list") do page.should have_css('li', :count => 3) end @rafaelkin,澄清一下:水豚现在是否报告例如?元素计数的不匹配更详细?我已经有一段时间没有关注 capybara 了,但是当时我提出问题时的问题是关于错误消息的格式,而不是page.should have_css("ol li", :count => 2)
不会已经实现。
伙计们,我觉得当前接受的答案(=我自己的)不再是最好的,但没有时间(不再使用 Ruby)来评估哪个建议的解决方案是最好的。我会将接受的答案更改为 Richard 的答案,因为它包含解决原始问题的断言输出。
【参考方案1】:
好吧,似乎没有开箱即用的支持,我编写了这个自定义匹配器:
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【参考方案2】:我更喜欢这个。
expect(page).to have_selector('input', count: 12)
https://github.com/jnicklas/capybara/blob/415e2db70d3b19b46a4d3d0fe62f50400f9d2b61/spec/rspec/matchers_spec.rb
【讨论】:
也适用于have_css
:expect(page).to have_css('input', count: 12)
【参考方案3】:
我认为以下更简单,输出相当清晰,并且不需要自定义匹配器。
page.all("ol li").count.should eql(2)
然后在错误时打印出来:
expected: 2
got: 3
(compared using eql?)
(RSpec::Expectations::ExpectationNotMetError)
【讨论】:
这不会等待期望成真,例如当仍有待处理的 ajax 请求时。【参考方案4】:Capybara 推荐的当前 (9/2/2013) 最佳实践如下 (source):
page.assert_selector('p#foo', :count => 4)
【讨论】:
【参考方案5】:@pandaPower 的回答非常好,但语法对我来说略有不同:
expect(page).to have_selector('.views-row', :count => 30)
【讨论】:
使用哈希火箭不符合“不同的语法”。 我不是 ruby 开发人员,也没有意识到这两种语法是等价的。 TBH 我不确定它是否值得被否决。这是一个有效的替代方案。对于那些没有 Ruby 背景的人来说,这似乎并不明显。它不适合我。【参考方案6】:编辑:正如@ThomasWalpole 指出的那样,使用all
会禁用Capybara 的等待/重试,因此@pandaPower 上面的答案要好得多。
这个怎么样?
within('ol') do
expect( all('.opportunity_title_wrap').count ).to eq(2)
end
【讨论】:
这完全打败了 Capybaras 等待/重试的方法,不应该成为推荐的解决方案。 @ThomasWalpole 我不确定你在说什么。在 Capybara 中以任何方式在另一个元素中寻找一个元素如何触及等待/重试? @ConstantMeiring 不是within
,而是在all
的结果上调用.count
禁用等待/重试。通过在all
的结果上调用count
(一个空的“数组”是一个有效的返回值),您可以将其转换为整数并进行比较。如果该比较失败,则期望失败。相反,如果您将 count 选项传递给 Capybara 的匹配器之一,capybara 将等待/重试查找指定的选择器,直到 count 选项匹配(或 Capybara.default_max_wait_time 到期)。以上是关于如何使用 Capybara 使用正确的错误消息断言元素数量?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用惰性加载器捕获 Capybara Feature JS 测试的服务器端错误?