您可以使用 TestRule 执行此操作。这将为您提供所需的灵活性。TestRule 允许您在测试周围插入逻辑,因此您将实现重试循环:
public class RetryTest {
public class Retry implements TestRule {
private int retryCount;
public Retry(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;
// implement retry logic here
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");
throw caughtThrowable;
}
};
}
}
@Rule
public Retry retry = new Retry(3);
@Test
public void test1() {
}
@Test
public void test2() {
Object o = null;
o.equals("foo");
}
}
的核心是 ,它调用您的测试方法。因此,在此调用周围,您放置了一个重试循环。如果在测试方法中引发异常(断言失败实际上是 ),则测试失败,您将重试。TestRule
base.evaluate()
AssertionError
还有一件事可能有用。您可能只想将此重试逻辑应用于一组测试,在这种情况下,您可以向 Retry 类中添加对方法上特定批注的测试。 包含方法的批注列表。有关此内容的更多信息,请参阅我对如何在每个 JUnit @Test 方法之前单独运行一些代码而不使用@RunWith和 AOP? 的回答。Description
使用自定义测试运行程序
这是CKuck的建议,你可以定义自己的Runner。您需要扩展BlockJUnit4ClassRunner并覆盖runChild()。有关详细信息,请参阅我对如何在套件中定义 JUnit 方法规则的回答?。此答案详细介绍了如何定义如何为套件中的每个方法运行代码,您必须为其定义自己的运行器。