Skip to content

Commit 786af13

Browse files
author
Veronika Lisovskaya
committed
Add RetryOnFailure
DEVSIX-1945
1 parent da09314 commit 786af13

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.itextpdf.test.runners;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* In current implementation it has no specified retries count
10+
*/
11+
@Retention(RetentionPolicy.CLASS)
12+
@Target({ ElementType.METHOD})
13+
public @interface RetryOnFailure {}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package com.itextpdf.test.runners;
2+
3+
import org.junit.AssumptionViolatedException;
4+
import org.junit.Ignore;
5+
import org.junit.internal.runners.model.EachTestNotifier;
6+
import org.junit.runner.Description;
7+
import org.junit.runner.notification.RunNotifier;
8+
import org.junit.runner.notification.StoppedByUserException;
9+
import org.junit.runners.BlockJUnit4ClassRunner;
10+
import org.junit.runners.model.FrameworkMethod;
11+
import org.junit.runners.model.InitializationError;
12+
import org.junit.runners.model.Statement;
13+
14+
/**
15+
* This class is used for flaky test retry after failure.
16+
* In current implementation we use specified retryCount = 3
17+
*/
18+
public class RetryRunner extends BlockJUnit4ClassRunner {
19+
private final int retryCount = 3;
20+
private int failedAttempts = 0;
21+
22+
public RetryRunner(Class<?> klass) throws InitializationError {
23+
super(klass);
24+
}
25+
26+
/**
27+
*
28+
* @param notifier RunNotifier
29+
*/
30+
public void run(RunNotifier notifier) {
31+
EachTestNotifier eachTestNotifier = new EachTestNotifier(notifier, getDescription());
32+
Statement statement = classBlock(notifier);
33+
try {
34+
statement.evaluate();
35+
} catch (AssumptionViolatedException ave) {
36+
eachTestNotifier.fireTestIgnored();
37+
} catch (StoppedByUserException sue) {
38+
throw sue;
39+
} catch (Throwable throwable) {
40+
retry(eachTestNotifier, statement, throwable);
41+
}
42+
}
43+
44+
/**
45+
*
46+
* @param method FrameworkMethod
47+
* @param notifier RunNotifier
48+
*/
49+
@Override
50+
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
51+
Description description = describeChild(method);
52+
if (method.getAnnotation(Ignore.class) != null) {
53+
notifier.fireTestIgnored(description);
54+
} else {
55+
runTestUnit(methodBlock(method), description, notifier);
56+
}
57+
}
58+
59+
/**
60+
* Runs an atomic test
61+
*/
62+
protected final void runTestUnit(Statement statement, Description description,
63+
RunNotifier notifier) {
64+
failedAttempts = 0;
65+
EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
66+
eachNotifier.fireTestStarted();
67+
try {
68+
statement.evaluate();
69+
} catch (AssumptionViolatedException avee) {
70+
eachNotifier.addFailedAssumption(avee);
71+
} catch (Throwable e) {
72+
retry(eachNotifier, statement, e);
73+
} finally {
74+
eachNotifier.fireTestFinished();
75+
}
76+
}
77+
78+
/**
79+
* Retry method, counts failed attempts, adds logging messages
80+
* @param notifier EachTestNotifier
81+
* @param statement Statement
82+
* @param currentThrowable Throwable
83+
*/
84+
private void retry(EachTestNotifier notifier, Statement statement, Throwable currentThrowable) {
85+
Throwable caughtThrowable = currentThrowable;
86+
while (retryCount > failedAttempts) {
87+
try {
88+
statement.evaluate();
89+
} catch (Throwable e) {
90+
System.out.println("Test Failed on attempt #" + (failedAttempts + 1));
91+
failedAttempts++;
92+
caughtThrowable = e;
93+
}
94+
}
95+
notifier.addFailure(caughtThrowable);
96+
}
97+
}

0 commit comments

Comments
 (0)