rspec 它在循环内阻塞

con*_*n-- 4 ruby rspec

我想测试页面上的每个链接是否返回特定的状态代码。我有一个工作测试,是这样的:

it "does not throw 400/500 error for any link" do
  visit '/'
  within(".wrapper") do
    all('a').each do |link|
      http_status = Faraday.head(link[:href].to_s).status
      puts "#{link.text}, #{http_status}"
      expect((400..500)).not_to include(http_status) 
    end
  end
Run Code Online (Sandbox Code Playgroud)

然而,这对于输出来说非常糟糕,因为所有链接都在一个测试中检查(因此测试中的 puts 向我显示哪个链接破坏了测试)。我希望能够对每个链接进行单独的测试,而无需为页面上的每个链接手动编写测试。

我试过这个:

context "does not throw 400/500 error for any link" do
  visit '/'
  within(".wrapper") do
    all('a').each do |link|
      it "does not throw 400/500 error for #{link}" do
        link_status_code_is_not(link, (400..500))
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

并得到这个错误

`visit` is not available on an example group (e.g. a `describe` or
`context` block). It is only available from within individual examples 
(e.g. `it` blocks) or from constructs that run in the scope of an 
example (e.g. `before`, `let`, etc).
Run Code Online (Sandbox Code Playgroud)

所以我尝试将访问移动到一个 before 钩子,但遇到了与内块相同的问题(我无法真正移动)。我已经能够在 jasmine 中做这样的事情,但我似乎找不到在 rspec 中做到这一点的方法。

tl:博士;有没有办法将 it 块放在 rspec 的循环中?

Sim*_*ime 5

您可以it在循环内创建一个块:

RSpec.describe "numbers" do
  [*1..10].each do |number|
    it "#{number} should not be multiple of 10" do
      expect(number % 10).not_to be_zero
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

您的问题是它看起来不像您可以visitit块之外(或“在示例范围内运行的构造”),并且您需要从页面中获取数据visit并循环遍历并it从中创建块数据。我不确定这是否可以很好地完成。

如果您想要的只是更好的链接输出,您可以aggregate_failures自定义消息一起使用,为您的测试提供更好的输出。对于人为的示例,假设我有大量动态,仅在it块内或在示例范围内运行的构造中可用,数字对,我需要确保它们的乘积都不是 10 的倍数:

RSpec.describe "numbers" do
  it "are not a multiple of 10" do
    [*1..10].product([*1..10]).each do |base, multiplier|
      expect((base * multiplier) % 10).not_to be_zero
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

这里的输出不是很好,它只是告诉我期望0.zero?返回 false,得到 true,而不是哪对数字失败。不过,通过使用聚合失败和自定义消息,我可以解决这个问题:

RSpec.describe "numbers" do
  it "are not a multiple of 10" do
    aggregate_failures do
      [*1..10].product([*1..10]).each do |base, multiplier|
        expect((base * multiplier) % 10).not_to be_zero, "#{base} * #{multiplier} is a multiple of 10"
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

现在,我在统计信息中只报告了 1 个失败(这对您的用例来说可能是好是坏),但我得到了 27 个子失败:

Failures:

  1) numbers are not a multiple of 10
     Got 27 failures from failure aggregation block.

     1.1) Failure/Error: ...
            1 * 10 is a multiple of 10
          # ...backtrace...
     1.2) Failure/Error: ...
            2 * 5 is a multiple of 10
          # ...backtrace...
     ...
     1.27) Failure/Error: ...
             10 * 10 is a multiple of 10
Run Code Online (Sandbox Code Playgroud)