ChatGPT解决这个技术问题 Extra ChatGPT

如何使用 Capybara 使用正确的错误消息断言元素数量?

我知道在 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 现在是否报告了元素计数的不匹配以及更多细节?我已经有一段时间没有关注 capybara 了,但是当时我提出问题时的问题是关于错误消息的格式,而不是 page.should have_css("ol li", :count => 2) 不会已经实现。
伙计们,我觉得目前接受的答案(=我自己的)不再是最好的,但是没有时间(不再使用 Ruby)来评估哪个建议的解决方案是最好的。我会将接受的答案更改为 Richard 的答案,因为它包含解决原始问题的断言输出。

p
pandaPowder

我更喜欢这个。

expect(page).to have_selector('input', count: 12)

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


也适用于 have_cssexpect(page).to have_css('input', count: 12)
m
merryprankster

好吧,似乎没有开箱即用的支持,我写了这个自定义匹配器:

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
R
Richard

我认为以下内容更简单,输出相当清晰,并且不需要自定义匹配器。

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

然后打印出错误:

      expected: 2
       got: 3

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

这不会等待期望成真,例如当仍有未决的 ajax 请求时。
C
Constant Meiring

编辑: 正如@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 到期)。
a
acconrad

Capybara 推荐的当前 (9/2/2013) 最佳做法如下 (source):

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


N
Nick

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

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

使用哈希火箭不符合“不同的语法”。
我不是 ruby 开发人员,也没有意识到这两种语法是等价的。 TBH 我不确定它是否值得投票。这是一个有效的替代方案。对于那些不是来自 Ruby 背景的人来说,这似乎并不明显。这不适合我。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅