我正在尝试改进现有的自动化 Selenium 测试系统。我的目标是重复由于连接问题而失败的测试。我找到并尝试关注这个线程如何立即重新运行失败的 JUnit 测试?这表明自己非常有用。
在我的例子中,套件是由类组成的,所以我尝试用@ClassRule 替换@Rule,以便在每次尝试时重复@Before 和@After 部分。我很抱歉我的无知,但我应该把这条规则放在哪里?在我的套房课上?或者在代表测试的类中?
我正在尝试改进现有的自动化 Selenium 测试系统。我的目标是重复由于连接问题而失败的测试。我找到并尝试关注这个线程如何立即重新运行失败的 JUnit 测试?这表明自己非常有用。
在我的例子中,套件是由类组成的,所以我尝试用@ClassRule 替换@Rule,以便在每次尝试时重复@Before 和@After 部分。我很抱歉我的无知,但我应该把这条规则放在哪里?在我的套房课上?或者在代表测试的类中?
如果我理解正确,您遇到的问题是由于@Before
在 中的代码之前执行RetryRule
,而在@After
之后执行。
因此,您当前的行为类似于:
@Before
@Retry
test code
@Retry
@After
但是你可以实现你的@Before
and@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
and @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
,则不再需要 and 上的注释@Rule
,但您需要.ExternalResource
RetryRule
RuleChain
这是我基于问题中提到的解决方案。
它是 a @Rule
, FailedRule和 a @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
你用or属性装饰测试名称本身:@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
是引发异常的 a 。
愿这能解决问题:
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
将包含测试运行的最后结果,因此在分析失败的测试后,您可以再次运行它。