IntelliJ:re运行 使用之前 运行 的数据随机测试间歇性失败

IntelliJ: rerun intermittently failing random test with previos run's data

我有一个包含许多测试的 JUnit 测试 class。为了增加场景覆盖率,我们测试中的一些数据是随机的,这意味着它可能在单个测试 运行 之间采用一系列值,例如:

protected MonthlyAmountWithRemainder getMonetaryAmountMultipleOf(int multiplier) {
    BigDecimal monthly = randomBigDecimal(1000);
    BigDecimal multiply = new BigDecimal(multiplier);
    BigDecimal total = monthly.multiply(multiply);
    return new MonthlyAmountWithRemainder(total, monthly, ZERO);
}

你看到这个 randomBigDecimal(1000) 了吗?这可能会生成 0 到 1000 之间的任何值。我们还可以在测试中随机化日期和其他一些值。

通常情况下,我们的测试 运行 还不错,但在极少数情况下(我说的当前情况是大约 50 次),测试会无缘无故地失败。可以想象,如此罕见的故障使得无法通过调试测试用例来找出故障原因或进行修复。

所以,问题是:是否可以捕获失败测试中生成的数据运行并使用完全相同的测试数据重新运行测试,以便我可以调试失败的场景?换句话说,我想重温我之前失败的测试运行。能实现吗?

简单:使用 seedseed 随机数生成器。 种子 可以从随机数生成器本身创建(这样你就可以为每个 运行 获得 不同的 个随机值)。核心点是然后 log 被使用的种子。

因为 "fail repro" 归结为不使用随机种子,而是使用导致测试失败的种子值。

当然:工作需要得到东西 "right" - 你想确保你真的 运行 使用不同种子的日常测试。但是您还想确保固定种子是微不足道的,并且会导致确定性的结果。

或者,无论何时出现随机数据,您都应该研究基于 "quickcheck" 的测试方法(例如,参见 here)。进入这种方法需要一些思考,但通常值得花时间。这个想法是您指定生产代码的某些 属性 - 然后框架生成随机数据并尝试伪造属性。真正好的部分是:一旦框架找到 break 属性的方法,它就会开始搜索导致问题的 minimal 示例.

谢谢@GhostCat。 以下是我们在项目中的处理方式:

测试 class 应该扩展以下 class:

import org.junit.rules.TestRule;
import org.junit.Rule;
public class RandomisedTest {
@Rule
public final TestRule randomisedRule = new RandomisedRule();
}

然后,当您有一个使用随机值的测试方法时,例如:

@Test
public void shouldDoStuff() {
...
}

失败了,在失败异常trace中会有一个seed number(很长,比如1516787460453)

为了 re-run 使用相同测试数据的测试,将以下注释附加到您的测试方法 header:

@Test
@RandomisedRule.Randomised(1516787460453)
public void shouldDoStuff() {
...
}

在 re-run 上,测试将使用与之前 运行 相同的测试数据。

希望对某人有所帮助!