Reputation: 8125
We are using TestNG for our integration tests. We recently converted from jUnit, and we used to use a org.junit.rules.TestRule
to automatically retry each test up to 3 times before counting it as failed. This eliminated a lot of false positives whenever a test case failed only occasionally.
In our conversion to TestNG, this retry rule was overlooked, and now we have a bunch of test cases "failing" that are really false positives.
I found a few articles on how to automatically re-run TestNG test cases:
https://jepombar.wordpress.com/2015/02/16/testng-adding-a-retryanalyzer-to-all-you-tests/
http://mylearnings.net/11.html
The gist of it is you can specify a retryAnalizer
for each individual @Test
-annotated test case. I set up my own analyzer and applied it to a test case, and that works. But applying a retry analyzer to every single test case manually is not a good solution, when we want every test case in the suite to do this. The article on jepombar.wordpress.com shows a way to apply it to all tests in a class, but for whatever reason it doesn't seem to work as written.
I made the following IAnnotationTransformer
:
public class RetryListener implements IAnnotationTransformer {
@Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
IRetryAnalyzer retry = annotation.getRetryAnalyzer();
if (retry == null) {
annotation.setRetryAnalyzer(RetryRule.class); // my TestNG RetryAnalizer implementation
}
}
}
And I apply it to a class like this:
@Listeners(RetryListener.class)
public class FooTest extends SeleniumMockedTest {
...
}
This doesn't work; the code in RetryListener.transform()
never executes, so RetryRule
is never added to any of the test cases for the class.
How can I get this to work?
Or, better yet, my real question: How can I get all the test cases in our integration test suite to automatically try 3 times before failing counts as actually failing?
Upvotes: 1
Views: 1743
Reputation: 154
Try this, Make 2 classes,
public class RetryAnalyzer implements IRetryAnalyzer {
int counter = 0;
@Override
public boolean retry(ITestResult result) {
RetryCountIfFailed annotation = result.getMethod().getConstructorOrMethod().getMethod()
.getAnnotation(RetryCountIfFailed.class);
result.getTestContext().getSkippedTests().removeResult(result.getMethod());
if((annotation != null) && (counter < annotation.value()))
{
counter++;
return true;
}
return false;
}
And write the other class to look like this
@Retention(RetentionPolicy.RUNTIME)
public @interface RetryCountIfFailed {
int value() default 0;
}
And now, pass the value of the count (retryCountGlobal) like below to every test you want to retry,
@Test
@listeners.RetryCountIfFailed(retryCountGlobal)
public void verifyRetryOnTestMethod(){
}
P.S : Remember that if retryCountGlobal=3, then the test will run 4 times, the first time if it fails, the test will be retried 3 more times.
Upvotes: 0