In this article, we will learn how to retry failed test in TestNG with IRetryAnalyzer and also how to rerun all tests from scratch in a test class. To retry a failed test, we will use the IRetryAnalyzer interface. It reruns the Selenium TestNG tests when they are failed. If you work on a test automation project, you’d know that the most difficult part of automation is the analysis of test executions. At the end of the execution, you need to analyze failed test cases and try to figure out if there’s any false positive/flaky situation caused by network glitch, time-out, or some other problem.
Also, some tests are dependent on each other and when a test fails maybe we want to run the tests before that test, in other words, we want to run the tests inside a test class from scratch. Also, I will explain how to rerun tests in a class for TestNG projects. Let’s start with how to rerun a failed test with IRetryAnalyzer.
How to Retry Failed Test in TestNG with IRetryAnalyzer
First of all, you need to create a separate class that implements this IRetryAnalyzer like the below example:
package retrysingletest; import org.testng.IRetryAnalyzer; import org.testng.ITestResult; public class Retry implements IRetryAnalyzer { private int count = 0; private static int maxTry = 3; @Override public boolean retry(ITestResult iTestResult) { if (!iTestResult.isSuccess()) { //Check if test not succeed if (count < maxTry) { //Check if maxtry count is reached count++; //Increase the maxTry count by 1 iTestResult.setStatus(ITestResult.FAILURE); //Mark test as failed return true; //Tells TestNG to re-run the test } else { iTestResult.setStatus(ITestResult.FAILURE); //If maxCount reached,test marked as failed } } else { iTestResult.setStatus(ITestResult.SUCCESS); //If test passes, TestNG marks it as passed } return false; } }
In case, you want to decrease or increase the re-run number of test cases, you need to change the maxTry value. In this example, failed test cases will run 3 times till it passes. In case it fails the third time, test execution will stop and TestNG will mark this case as failed.
Using retryAnalyzer attribute in the @Test annotation
The next step is to associate your test cases with IRetryAnalyzer. In order to do this, you need to use the method below.
@Test(retryAnalyzer = Retry.class)
public void testCase() {
}
In TestNG Listeners article I described how to use the listener. I will go on with that example and Retry Class in that project. Also, I changed SampleTest.java test class as follows.
package retrysingletest; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; public class RetryOnlyFailedTests extends BaseTest{ @Test(retryAnalyzer = Retry.class) public void test1() { //Negative Scenario assertEquals(2+2,5,"Addition Problem! 2+2 must be 4!\n"); } @Test(retryAnalyzer = Retry.class) public void test2() { //Negative Scenario assertEquals(2+2,3,"Addition Problem! 2+2 must be 4!\n"); } @Test(retryAnalyzer = Retry.class) public void test3() { //Postive Scenario assertEquals(2+2,4,"Addition Problem! 2+2 must be 4!\n"); } }
In the above scenario, test1 and test 2 re-runs 3 times and it fails during each execution. In the Retry class’s retry method, when the count is 3, it is smaller than maxTry and the test goes to the else branch and the test fails. However, test3 passed at the first execution as shown below.
Using Retry Class with ITestAnnotationTransformer Interface
Due to the static nature of Annotations, recompilation is needed when you want to change values. You can override this behavior at runtime with IAnnotationTransformer listener. IAnnotationTransformer is a TestNG listener which allows you to modify TestNG annotations and configure them further during runtime.
Transform method is called for every test during the test run. We can use this listener for our retry analyzer as shown below:
package retrysingletest; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import org.testng.IAnnotationTransformer; import org.testng.annotations.ITestAnnotation; public class AnnotationTransformer implements IAnnotationTransformer { @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { annotation.setRetryAnalyzer(Retry.class); } }
We need to add also this listener in our TestNG.xml file.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="TestNG retrysingletest.Listener Example"> <listeners> <listener class-name="retrysingletest.Listener"/> <listener class-name="retrysingletest.AnnotationTransformer"/> </listeners> <test name="TestNG Sample Test" preserve-order="true"> <classes> <class name="retrysingletest.RetryOnlyFailedTests"/> </classes> </test> </suite>
From now on, we do not need to specify “@Test(retryAnalyzer = Retry.class)” in this annotation. We can just only use @Test annotation without retryAnalyzer attribute.
package retrysingletest; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; public class RetryOnlyFailedTests extends BaseTest{ @Test public void test1() { //Negative Scenario assertEquals(2+2,5,"Addition Problem! 2+2 must be 4!\n"); } @Test public void test2() { //Negative Scenario assertEquals(2+2,3,"Addition Problem! 2+2 must be 4!\n"); } @Test public void test3() { //Positive Scenario assertEquals(2+2,4,"Addition Problem! 2+2 must be 4!\n"); } }
At this time, we will get the same result if we run the tests. :)
For IRetryAnalyzer, we learned two different ways how to use Retry logic in your TestNG tests. You can use both of the methods depends on your needs.
How to Rerun All Tests in a Class When one of them Fails in TestNG
In order to run the tests from scratch when one of them fails, we can use a different strategy. For this first, we should add the below code snippet in TestListener’s onTestFailure method.
private static int count = 0; private final static int maxTry = 1; public void onTestFailure(ITestResult iTestResult) { System.out.println("I am in onTestFailure method " + getTestMethodName(iTestResult) + " failed") if (count < maxTry) { count++; TestNG tng = new TestNG(); tng.setDefaultTestName("RETRY TEST"); Class[] classes1 = { iTestResult.getTestClass().getRealClass() }; tng.setTestClasses(classes1); tng.addListener(new TestListener()); tng.run(); } }
and our Test Class is shown below.
package retryfromscratch; import static org.testng.Assert.fail; import org.testng.annotations.Test; public class RerunTestsInAClassWhenATestFailsTest { @Test public void testStep_1() { System.out.println("Test 1 starting."); System.out.println("Test 1 passed."); } @Test public void testStep_2() { System.out.println("Test 2 starting."); System.out.println("Test 2 passed."); } @Test public void testStep_3() { System.out.println("Test 3 starting."); System.out.println("Test 3 failed."); fail("Test 3 failed."); } }
The TestNG suite XML also looks like below.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="TestNG retrysingletest.Listener Example"> <listeners> <listener class-name="retryfromscratch.TestListener"/> </listeners> <test name="TestNG Sample Test"> <classes> <class name="retryfromscratch.RerunTestsInAClassWhenATestFailsTest"/> </classes> </test> </suite>
When we run the test by right-clicking our test suite XML file. We will get the below results. The tests will fail at the 3rd test and after that not only test3 all of the tests will run again one more time.
GitHub Project
https://github.com/swtestacademy/TestNGListener/tree/Retry
Thanks for reading,
Onur Baskirt & Canberk Akduygu

Onur Baskirt is a Software Engineering Leader with international experience in world-class companies. Now, he is a Software Engineering Lead at Emirates Airlines in Dubai.
Nice post.
Really informative
Thank you. :)
Finally!
Finally a tutorial with USEFUL examples, not like “System.out.println(“this is @BeforeMethod”);”
Thank you! Your site is a gem among mounts of garbage that somehow populate the top places in search.
Thank you so much Andrey. :)
Thanks for the Article.
Do you know how we can rerun failed Cucumber scenarios when you use TestNG. It will be really helpful. Thanks
Hi Deyan, I have not any experience on that. Did you try this code? Is it not working? I will try to check this also.
Thanks for the response Onur,
I haven’t tried the code, but I am sure it is not working because Cucumber is not using the TestNG annotations but the Cucumber ones.
Also you can not run tests in parallel with Cucumber and TestNG the same way with TestNG, you need to use this pluging:
https://github.com/temyers/cucumber-jvm-parallel-plugin/issues/31
And it looks like they are trying to develop a Retry for failed scenarios.
Hi Onur or Deyan , it will be very helpfull for me if you guys found any solution for re-running failed cucumber scenarios in testng
Please check this solution: https://stackoverflow.com/questions/21334207/rerunning-failed-cucumber-tests-using-cucumber-jvm
Can i put the retry analyzer at the class level and not for each method?
İn this example, it is in class level. You dont have any Retry annotation in Test classes. You just implement some class and add this implemented class as a listener into your testng.xml file.
Or am i missing something?
Can you please tell me at what point retry gets executed.
ie. After @Test or @After method or whenever the test gets failed.
Whenever the test gets failed.
Hi Onur,
Currently i am facing a problem in my Framework.
As while i am making a test fail Explicitly then retry is not getting executed.
Hi Onur,
Currently i am facing a problem in my Framework.
As while i am making a test fail Explicitly then retry is not getting executed.
https://github.com/Akashkansal065/FirstFrameWork
Not able to understand why the test is not getting retry.
Is there any way to execute Retry only after running of @After method for failed @Test.
Please check the second example. It is happening when a test fails. You can apply the same code @After method by moving that code to the @After method.
Thank you for the post but its not working with @factory, just executed the @test one time and when we give counter as 3 to re-run for fail test cases, the rest get skipped.
Hi Sumeet, I did not use it with @factory annotation. Someone also had problems here: https://www.gitmemory.com/issue/allure-framework/allure-java/141/486531576
Would you try this with the latest TestNG version? Maybe it has been addressed and fixed.
Hi
This retry is not working if we run test case with test data
Would you please elaborate “test data” part, please?
That solution doesn’t work for DataProviders
This will be a work around
package pwae2e;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
import java.util.HashMap;
import java.util.Map;
public class TestNGRetry implements IRetryAnalyzer {
private static final int MAX_ATTEMTPS = 2;
private static Map TESTS = new HashMap();
@Override
public boolean retry(ITestResult iTestResult) {
String testName = buildTestName(iTestResult);
if (!iTestResult.isSuccess()) {
if(!TESTS.containsKey(testName))
TESTS.put(testName, 1);
int count = TESTS.get(testName);
if (count < MAX_ATTEMTPS) {
TESTS.put(testName, count+1);
iTestResult.setStatus(ITestResult.FAILURE);
return true;
} else {
iTestResult.setStatus(ITestResult.FAILURE);
}
} else {
iTestResult.setStatus(ITestResult.SUCCESS);
}
return false;
}
public static String buildTestName(ITestResult iTestResult){
String testName = iTestResult.getName();
if (iTestResult.getParameters().length != 0) {
String parameters = "";
for (int i = 0; i< iTestResult.getParameters().length; i++){
String parameter = iTestResult.getParameters()[i].toString();
if(i != 0)
parameters = parameters + "-" + parameter;
else
parameters = parameter;
}
testName = iTestResult.getName() + "-" + parameters;
}
return testName;
}
}
Many thanks (Only fix to: int count = (int) TESTS.get(testName); )
Onur Bey, I have been following your articles since 2017 and you have done amazing works. I really appreciate your hard work and valuable time. I was wondering that if you will come up with real-time interview questions and answers. Thank you very much
Hi, thank you very much for your kind comment. I have started to update the articles and try to add new ones. After updating old articles, I am planning to share my new experiences and better articles soon. :)
Hi…thanks for such an informative post. But i have one query – How to re-run whole class in case any of it’s @Test methods fails as they have dependency on another @Test Methods.
Thank you, for this, I found on the web this solution: https://stackoverflow.com/questions/59160655/re-running-complete-class-and-not-just-test-in-testng
Honestly, I spent a couple of hours and I tried this solution but I could not be successful. :(
I have implemented a logic. Please, check the git repo:
I will also update the blog post. It was a really good problem to solve. :) Thank you. I hope my solution will help.
Git Repo: https://github.com/swtestacademy/TestNGListener/tree/Retry
Clone the repo and please run the ‘TestNG_Tests_From_Scratch_Suite.xml’
Hi I have doubt
If our test case failed for first time and then in second it get passed then how to remove the first failed report in Extend html report
I am not sure there is this kind of feature in Extent Reports. I think we should better ask the extent reports maintainers. Here you can create a ticket for it: https://github.com/extent-framework/extentreports-java/issues
Very nice and informative post! Thank you!
Although I do have a question :
I have an @AfterTest or @AfterClass annotation method which tends to fail, so I wanted to retry that method. However TestNG doesn’t allow or have the option for retryAnalyzer. Is there a workaround for this ?
I have something like,
””
public boolean retry(ITestResult testResult) {
if (!testResult.isSuccess()) { //Check if test not succeed
if (count < retryLimit) { //Check if retryLimit count is reached
count++; //Increase the retryLimit count by 1
System.out.println("Retry #" + count + " for test case " +
testResult.getMethod().getMethodName());
testResult.setStatus(ITestResult.FAILURE); //Mark test as failed
return true; //Tells TestNG to re-run the test
} else {
testResult.setStatus(ITestResult.FAILURE); //If maxCount reached,test marked as failed
}
} else {
testResult.setStatus(ITestResult.SUCCESS); //If test passes, TestNG marks it as passed
}
return false;
}
''''
Here, When the Test fails both the times, it console logs as RUN 1: PASS and in the retry it says fails.
Although the reporting is done correctly.
Can someone help resolve the console log misleading INFO about RUN 1: PASS ?
Hi any way we can re-run failed test cases in cucumber framework?