代码之家  ›  专栏  ›  技术社区  ›  Obromios

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

  •  2
  • Obromios  · 技术社区  · 6 年前

    我有一个99%置信极限的算法。所以如果我设置这样的测试

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

    它将失败1%。我可以编写一个测试,在数千个有效的输入信号上运行我的_检测器,检查它只有1%的时间失败,但这需要很长的时间才能运行,测试的目的不是检查算法的工作情况,但破坏算法的代码没有任何变化。

    我认为实现这一点的有效方法是再次运行上面的测试,如果它通过了,就给它一个通过。如果第二次失败,那么给它一次失败,因为假设基数正确,它连续失败两次的概率是1/10000。当然,这意味着1/10000的组合测试将在有效的代码基础上失败,但这比目前的情况要好得多,即1/100的测试失败。

    那么,rspec中是否有一种方法可以做到这一点,即如果第一次失败,则第二次运行测试,如果第二次失败,则只输出失败?

    2 回复  |  直到 6 年前
        1
  •  1
  •   aridlehoover    6 年前

    试试这个:

    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
    
        2
  •  2
  •   Greg    6 年前

    测试的目的并不是检查算法的工作情况,但是代码中没有任何改变破坏了算法。

    您不能在随机生成的输入数据中测试它。假设你有一组100个有效的输入信号,它在第五个信号上失效,没关系。有人改变了算法,它从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 ,检查并确认为真阴性(假定返回假),将其保存在其他地方,并为其制定规格:

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

    比方说(人工检查之后)只有8个是真的负的,剩下的2个应该是真的,但返回的是假的——这些可能是错误。以后再保存。

    你对1000个样品的覆盖率满意吗?磨合需要多长时间?你能把这次的一些样品换成10000个样品吗?100万?这是你的选择。

    在某种程度上,添加更多的样本是没有意义的。现在,您已经粗略地覆盖了整个算法,并且可以开始一些基本的重构,比如 extract method name magic constants 并提取逻辑组件(在本答案第2段中提到)。X样本测试是临时的,它们可以确保(尽可能多地使用非无限样本大小)整个算法的行为不会改变,同时您可以凿除您更好理解的部分。