问题描述
有没有办法让JUnit规则或类似的东西为每次失败的测试提供第二次机会,只需尝试再次运行它。
Is there a way to have an JUnit Rule or something similar that gives every failing test a second chance, just by trying to run it once again.
背景:我有一大堆用JUnit编写的Selenium2-WebDriver测试。由于非常激进的时间(点击后只有很短的等待时间),一些测试(100个中的1个,总是不同的测试)可能会失败,因为服务器有时响应速度稍慢。但是我不能让等待时间太久以至于它足够长,因为那时测试将永远持续下去。) - 所以我认为这个用例即使它需要一秒也是绿色的测试是可以接受的尝试。
当然最好有2分(满分3分)(重复3次失败测试,并将其视为正确,如果其中两个测试是正确的),但这将是未来的改进。
Of course it would be better to have a 2 out of 3 majority (repeat a failing test 3 times, and take them as correct, if two of the tests are correct), but this would be a future improvement.
推荐答案
你可以用。这将为您提供所需的灵活性。 TestRule允许您在测试周围插入逻辑,因此您将实现重试循环:
You can do this with a TestRule. This will give you the flexibility you need. A TestRule allows you to insert logic around the test, so you would implement the retry loop:
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
),则测试失败,您将重试。
The heart of a TestRule
is the base.evaluate()
, which calls your test method. So around this call you put a retry loop. If an exception is thrown in your test method (an assertion failure is actually an AssertionError
), then the test has failed, and you'll retry.
还有一件事可能有用。您可能只想将此重试逻辑应用于一组测试,在这种情况下,您可以在方法的特定注释的测试上方添加到Retry类中。 描述
包含该方法的注释列表。有关这方面的更多信息,请参阅我对。
There is one other thing that may be of use. You may only want to apply this retry logic to a set of tests, in which case you can add into the Retry class above a test for a particular annotation on the method. Description
contains a list of annotations for the method. For more information about this, see my answer to How to run some code before each JUnit @Test method individually, without using @RunWith nor AOP?.
这是CKuck的建议,您可以定义自己的Runner。您需要扩展并覆盖runChild()。有关详细信息,请参阅我对。此答案详细说明了如何定义如何为Suite中的每个方法运行代码,您必须为其定义自己的Runner。
This is the suggestion of CKuck, you can define your own Runner. You need to extend BlockJUnit4ClassRunner and override runChild(). For more information see my answer to How to define JUnit method rule in a suite?. This answer details how to define how to run code for every method in a Suite, for which you have to define your own Runner.
这篇关于如何立即重新运行失败的JUnit测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!