结果随机时,运行rspec测试两次

时间:2018-12-21 05:38:11

标签: rspec

我有一个算法可以在99%的置信度下工作。所以如果我设置这样的测试

let(:valid_input_signal) { randomly_generate_signal_plus_noise }
it { expect(my_detector(valid_input_signal).signal_present?).to be true }

它将失败1%的时间。我可以编写一个对数千个有效输入信号运行my_detector的测试,并检查它仅在1%的时间内失败,但这将花费很长时间,并且测试的目的不是检查算法是否有效,而是代码中没有任何改变算法的更改。

我认为实现此目的的有效方法是第二次运行上述测试,如果通过了,则给它通过。如果它第二次失败,则给它一次失败,因为假设基数正确,它连续两次失败的机会是10,000分之一。当然,这意味着在有效代码库中,每10,000倍的组合测试将失败,但这比目前的情况要好得多,后者在100倍的测试中失败。

那么rspec中是否有办法做到这一点,即如果第一次失败则第二次运行测试,而如果第二次失败则仅输出失败?

2 个答案:

答案 0 :(得分:2)

  

,测试的目的不是检查算法是否有效,而是破坏算法的代码没有变化。

您无法在随机生成的输入数据中进行测试。假设您有一组100个valid_input_signals,但它在第5个失败,没关系。有人更改了算法,它从第5个开始通过,到第17个失败。在1%的情况下,它仍然会失败,但是仍然正确吗?

如何从此处继续尚不清楚-它取决于算法的作用。也许您可以将某些部分提取到单一职责组件中,并进行单独测试?

但是也许这是一个遗留算法,您需要尽可能多地用规格覆盖它吗?如果是这样-我会以覆盖速度为代价:

生成1000个信号,并将my_detector(valid_input_signal).signal_present? == true的信号保存,保存在文件或其他内容中,并针对确定的输入运行规范。

valid_inputs.each do |input| 
  expect(my_detector(input).signal_present?).to be true
end

让我们说其中的10个给出false,检查并确认这是一个真实的否定项(假定返回false),将它们保存在其他位置并为其指定规格:

invalid_inputs.each do |input| 
  expect(my_detector(input).signal_present?).to be false
end

让我们说(经过手动检查),其中只有8个为真阴性,剩下的2个应该返回true,但返回false-这些可能是错误。保存以备后用。

您对1000个样本的覆盖范围满意吗?跑步需要多长时间?您可以在这段时间内进行交易并将覆盖率增加到10000个样本吗?百万?这是你的选择。

在某些时候添加更多样本毫无意义。现在,您已经大致了解了整个算法,并且可以开始一些基本的重构,例如extract methodname magic constants并提取逻辑组件(在此答案的第2部分中提到)。 X样本测试是临时的,它们确保(尽可能多地使用非无限样本大小),当您删除一部分您更了解的算法时,整个算法的行为不会改变。

答案 1 :(得分:1)

尝试一下:

describe '#my_decorator' do
  let(:valid_input_signal_1) { randomly_generate_signal_plus_noise }
  let(:valid_input_signal_2) { randomly_generate_signal_plus_noise }

  it 'should not fail twice in a row' do
    fail unless my_detector(valid_input_signal_1).signal_present? || my_detector(valid_input_signal_2).signal_present?
  end
end