我正在努力改进现有的自动化Selenium测试系统。 我的目标是重复因连接问题而失败的测试。 我发现并试图遵循这个显示自己非常有用的线程How to Re-run failed JUnit tests immediately?。
在我的情况下,套件由类组成,所以我试图用@ClassRule替换@Rule,以便重复每次尝试@Before和@After部分。 对不起我很抱歉,但我应该把这条规则放在哪里?在我的套件课程中?或者在代表测试的类中?
答案 0 :(得分:4)
以下是基于问题中提到的解决方案。
它是@Rule
, FailedRule 和@ClassRule
, RetryRule
public class RetryTest
{
public static class FailedRule implements TestRule
{
@Override
public Statement apply(final Statement base, final Description description)
{
return new Statement()
{
@Override
public void evaluate() throws Throwable
{
try
{
base.evaluate();
}
catch (Throwable t)
{
System.out.println(description.getDisplayName() + " failed");
retry.setNotGood();
if (retry.isLastTry())
{
System.out.println("No more retry !");
throw t;
}
else
{
System.out.println("Retrying.");
}
}
}
};
}
}
public static class RetryRule implements TestRule
{
private int retryCount, currentTry;
private boolean allGood = false;
public RetryRule(int retryCount)
{
this.retryCount = retryCount;
this.currentTry = 1;
}
public boolean isLastTry()
{
return currentTry == retryCount;
}
public void setNotGood()
{
allGood = false;
}
public Statement apply(final Statement base, final Description description)
{
return new Statement()
{
@Override
public void evaluate() throws Throwable
{
// implement retry logic here
for (; currentTry <= retryCount && !allGood; currentTry++)
{
allGood = true;
System.out.println("Try #" + currentTry);
base.evaluate();
}
}
};
}
}
@ClassRule
public static RetryRule retry = new RetryRule(3);
@Rule
public FailedRule onFailed = new FailedRule();
@BeforeClass
public static void before()
{
System.out.println("Before...");
}
@AfterClass
public static void after()
{
System.out.println("...After\n");
}
@Test
public void test1()
{
System.out.println("> test1 running");
}
@Test
public void test2()
{
System.out.println("> test2 running");
Object o = null;
o.equals("foo");
}
}
它给出了:
Try #1
Before...
> test1 running
> test2 running
test2(RetryTest) failed
Retrying.
...After
Try #2
Before...
> test1 running
> test2 running
test2(RetryTest) failed
Retrying.
...After
Try #3
Before...
> test1 running
> test2 running
test2(RetryTest) failed
No more retry !
...After
如果我在o.equals("foo");
中评论test2
,那么在第一次尝试中一切正常:
Try #1
Before...
> test1 running
> test2 running
...After
答案 1 :(得分:4)
我是How to Re-run failed JUnit tests immediately?
的原始回答者如果我理解正确,您遇到的问题是@Before
之前执行RetryRule
,之后执行的@After
。
所以你现在的行为是这样的:
@Before
@Retry
test code
@Retry
@After
但您可以实施@Before
和@After
作为规则 - 有一条规则ExternalResource就是这样做的。您将实施@Before
和@After
作为规则:
@Rule public ExternalResource beforeAfter = new ExternalResource() {
public void before() {
// code that was in @Before
}
public void after() {
// code that was in @After
}
}
然后您不需要@Before
和@After
。然后,您可以使用RuleChain链接这些规则。这会强制执行您的规则:
@Rule public RuleChain chain= RuleChain
.outerRule(new LoggingRule("outer rule")
.around(new LoggingRule("middle rule")
.around(new LoggingRule("inner rule");
因此,您的最终解决方案将是:
private ExternalResource beforeAfter = ...
private RetryRule retry = ...
@Rule public RuleChain chain = RuleChain
.outerRule(retry)
.around(beforeAfter);
请注意,如果您使用的是RuleChain
,则不再需要@Rule
和ExternalResource
上的RetryRule
注释,而是RuleChain
答案 2 :(得分:0)
您使用@After
或@Afterclass
属性装饰测试名称:
@After
@Test
@Category(SmokeTests.class)
public void testProductPageOnly() throws TimeoutException {
//Some tests here.
}
@Afterclass
public static void SomeTest {
//Some test here.
}
需要注意的是,@Afterclass
将始终运行;即使您使用引发异常的@Beforeclass
。
答案 3 :(得分:0)
这可以解决问题:
1)测试类应继承自junit.framework.TestCase
2)使用类似的东西运行测试
YourTestClass testClass = new YourTestClass();
TestResult result = testClass.run();
Enumeration<TestFailure> failures = result.failures();
if (result.failureCount() != 0)
{
TestFailure fail = failes.nextElement();
junit.framework.Test test = fail.failedTest();
test.run( result );
}
最后result
将包含测试运行的最后结果,因此在分析了哪些测试失败后,您可以再次运行它。