Java 如果失败,如何在SuiteClass中重试JUnit测试?
我有以下RetryRule类:Java 如果失败,如何在SuiteClass中重试JUnit测试?,java,unit-testing,junit,test-suite,Java,Unit Testing,Junit,Test Suite,我有以下RetryRule类: public class RetryRule implements TestRule { private int retryCount; public RetryRule(int retryCount) { this.retryCount = retryCount; } public Statement apply(Statement base, Description description) {
public class RetryRule implements TestRule {
private int retryCount;
public RetryRule(int retryCount) {
this.retryCount = retryCount;
}
public Statement apply(Statement base, Description description) {
return statement(base, description);
}
private Statement statement(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
Throwable caughtThrowable = null;
for (int i = 0; i < retryCount; i++) {
try {
base.evaluate();
return;
}
catch (Throwable t) {
caughtThrowable = t;
System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed.");
}
}
System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures.");
if (caughtThrowable != null) {
throw caughtThrowable;
}
}
};
}
}
这有两个测试类MakeBookingTest和PaymentTest。它们每个都有多个JUnit测试
我希望在失败的情况下重试。你知道我怎样才能做到吗
编辑:为了更好地理解,您可以使用我的代码给示例添加什么。谢谢非常感谢。根据给出的评论,这是一个明显的非答案:
有时它会失败,因为它们可能是片状的。但是99%的时间,如果我重新运行。。。它起作用了 在这种情况下,投入您的时间和精力以说服您的测试设置进行“重新运行”。。。最有可能的是:一项糟糕的投资 你的问题不是重试。你的真正的问题是你的测试不可靠。你把所有的时间和精力都花在理解你的测试不可靠的原因上,然后解决这个问题
任何其他事情都会毫无理由地增加设置的复杂性。您编写的特殊代码需要维护,更糟糕的是:所有未来的读者都必须理解“是的,这些测试在那里,我们只是重试,直到它们通过”。这是人们迟早会接受的信息。首先,我同意GhostCat。
真正的问题是测试代码不稳定 但是,如果代码中没有“flakeynes”(例如,到外部web服务的坏网络连接),那么重新运行测试可能会很有用 在这种情况下,您可以执行以下操作 首先创建一个接口注释。 (这将用于指示哪些测试需要重试。) 然后在我们的测试中应用
TestRule
。
(如果存在重试
注释,则此规则将检查失败)
最后在我们的测试中,我们把所有的东西放在一起
public class RetryTest {
private static int count = 0;
@Rule
public RetryRule rule = new RetryRule();
@Test
@Retry
public void testToRetry() throws Exception {
callMyFlakeyCode();
}
}
别误会我。。。但是为什么呢?您希望从重新运行失败的测试中获得什么?有时它会失败,因为它们可能是片状的。但是99%的时间,如果我重新运行。。。它起作用了。午夜运行的jenkins作业运行suiteclass。所以,理想情况下,它应该重试任何失败的测试。好的,我同意你的建议。调查它们为什么会变薄并修复它们是有意义的。尽管如此,您能否提供一些关于如何进行重试的信息知道如何在当前环境下执行这些操作会很好。@saffik问题是:这可能需要一些时间坐下来尝试测试。我现在没有时间;-)。。。如果我有一个好的技术答案,我会把它包括进去。一个真实的情况是,在代码中有片状的部分,需要
@Retry
:我们想测试一个方法大约80%的输出是真的
,而剩下的是假的
;该方法本身不是确定性的,但我们想要的是一个粗略的正确性(它用于平衡对目标a和B的大量请求)。在这种情况下,现在我将单个测试的百分比范围调整为[0.77,0.83]
,但我发现它太宽了。所以我想缩小范围,但增加执行次数,以防失败。@WesternGun谢谢。这是一个有趣的方法。但是我想知道我们是否仍然在谈论“真正的”单元测试,或者这更像是一个函数/集成测试,恰好使用JUnit框架;-)我同意它更实用;我只想声明,在某些情况下,单次执行的结果是不确定的,但从统计上看,该方法做了它应该做的事情。不过,这种情况很奇怪。但是现在我们已经在谈论重试了。。。我们已经知道有些东西很奇怪/不稳定。非常有趣。问题仍然是,我如何在SuiteClass中应用这一点,而不是在每个测试中单独应用?正如我在问题中提到的(带示例)代码:)这应该在不接触SuiteClass的情况下工作。或者,您是否试图重新运行整个TestClass,即使该TestClass中只有一个测试失败?这似乎不是一个很有帮助的行为。是的,那么我应该在每个测试类中添加@Rule,而不是触摸SuiteClass吗?如果我理解正确的话?我有55个测试班。。。在当前上下文中,我只包含了两个。是的,将规则添加到TestClass。并将重试注释添加到要在该TestClass中重新测试的特定测试中。
@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {}
public class RetryRule implements TestRule {
@Override
public Statement apply(Statement base, Description method) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (Throwable t) {
Retry retry = method.getAnnotation(Retry.class);
if (retry != null) {
base.evaluate();
} else {
throw t;
}
}
}
};
}
}
public class RetryTest {
private static int count = 0;
@Rule
public RetryRule rule = new RetryRule();
@Test
@Retry
public void testToRetry() throws Exception {
callMyFlakeyCode();
}
}