How to Configure Retry Failed Tests with IRetryAnalyzer in TestNG
Use the IRetryAnalyzer interface combined with an IAnnotationTransformer to automatically re-run failing tests based on a configurable count defined in FrameworkConstants.RETRY_TEST_FAIL.
The automationframeworkselenium repository provides a complete, property-driven solution to configure retry failed tests with IRetryAnalyzer in TestNG without modifying individual test classes. This implementation centralizes retry logic through a global annotation transformer and a configurable constant that determines how many extra attempts a failing test receives.
Core Components of the Retry Mechanism
The framework implements automatic test retry through three integrated components that work together during TestNG's lifecycle.
FrameworkConstants Configuration
The retry count is controlled by the RETRY_TEST_FAIL constant defined in src/main/java/com/anhtester/constants/FrameworkConstants.java. This value is loaded from the properties files during class initialization via a static block.
// In FrameworkConstants.java
public static final String RETRY_TEST_FAIL = "1"; // Default value from config.properties
The constant reads its value from src/test/resources/config/config.properties, allowing you to adjust retry behavior without recompiling code.
Retry Class Implementation
The Retry class in src/test/java/com/anhtester/listeners/Retry.java implements org.testng.IRetryAnalyzer to handle the actual retry logic. It maintains a per-test counter and compares it against the maximum allowed attempts.
package com.anhtester.listeners;
import com.anhtester.constants.FrameworkConstants;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
public class Retry implements IRetryAnalyzer {
private int count = 0;
private static final int maxTry = Integer.parseInt(FrameworkConstants.RETRY_TEST_FAIL);
@Override
public boolean retry(ITestResult result) {
if (!result.isSuccess() && count < maxTry) {
count++;
result.setStatus(ITestResult.FAILURE);
return true; // Request TestNG to re-run the test
}
result.setStatus(result.isSuccess() ? ITestResult.SUCCESS : ITestResult.FAILURE);
return false;
}
}
AnnotationTransformer for Global Registration
Rather than adding @Test(retryAnalyzer = Retry.class) to every test method, the framework uses AnnotationTransformer in src/test/java/com/anhtester/listeners/AnnotationTransformer.java to inject the retry analyzer globally.
package com.anhtester.listeners;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class AnnotationTransformer implements IAnnotationTransformer {
@Override
public void transform(ITestAnnotation annotation,
Class testClass,
Constructor testConstructor,
Method testMethod) {
annotation.setRetryAnalyzer(Retry.class);
}
}
Step-by-Step Configuration Guide
1. Set the Retry Count in Properties
Edit src/test/resources/config/config.properties to specify how many times a failed test should be re-attempted:
# Number of extra attempts for a failed test
RETRY_TEST_FAIL = 2
Setting this to 2 allows a total of three executions (initial attempt plus two retries). The FrameworkConstants class automatically reloads this value on the next test run.
2. Register the Transformer in TestNG XML
Add the AnnotationTransformer listener to your TestNG suite XML files located in src/test/resources/suites/. For example, in src/test/resources/suites/CRM/SignIn-simple.xml:
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="CRM SignIn Suite" parallel="tests" thread-count="2">
<listener class-name="com.anhtester.listeners.AnnotationTransformer"/>
<test name="SignIn Tests">
<classes>
<class name="com.anhtester.projects.crm.testcases.SignInTest"/>
</classes>
</test>
</suite>
3. Alternative Programmatic Registration
If you execute TestNG programmatically, register the transformer in your Java code:
import com.anhtester.listeners.AnnotationTransformer;
import org.testng.TestNG;
import java.util.Collections;
public class TestRunner {
public static void main(String[] args) {
TestNG testng = new TestNG();
testng.setListenerClasses(Collections.singletonList(AnnotationTransformer.class));
testng.setTestClasses(new Class[]{SignInTest.class});
testng.run();
}
}
How the Retry Flow Works
When you configure retry failed tests with IRetryAnalyzer in TestNG using this framework, the execution follows this sequence:
- Initialization:
FrameworkConstantsloads all properties files viaPropertiesHelpers.loadAllFiles()in its static initializer - Annotation Processing: As TestNG parses the suite XML,
AnnotationTransformer.transform()executes for every test method, assigningRetry.classas the retry analyzer - Failure Detection: When a test fails, TestNG invokes
Retry.retry(ITestResult) - Retry Decision: If the internal counter is less than
maxTry(parsed fromRETRY_TEST_FAIL), the method increments the counter and returnstrue, triggering a re-run - Final Status: Once the maximum retry count is reached, the method returns
falseand the test is marked as finally failed
This approach ensures zero changes to individual test classes while providing centralized control over retry behavior.
Summary
- Configuration: Set
RETRY_TEST_FAILinsrc/test/resources/config/config.propertiesto control maximum retry attempts - Implementation: The
Retryclass insrc/test/java/com/anhtester/listeners/Retry.javaimplementsIRetryAnalyzerwith a per-test counter mechanism - Global Application:
AnnotationTransformerinsrc/test/java/com/anhtester/listeners/AnnotationTransformer.javaautomatically injects the retry analyzer into every test method viasetRetryAnalyzer() - Registration: Add the transformer to your TestNG suite XML or register it programmatically to enable the functionality
- Source Files: Key files include
FrameworkConstants.javafor configuration,Retry.javafor logic, and suite XML files for listener registration
Frequently Asked Questions
How do I change the number of retry attempts without modifying Java code?
Update the RETRY_TEST_FAIL property in src/test/resources/config/config.properties. The FrameworkConstants class loads this value at runtime, so changes take effect immediately without recompilation.
Why use AnnotationTransformer instead of @Test annotation attributes?
The AnnotationTransformer approach eliminates the need to add retryAnalyzer = Retry.class to every test method. As implemented in src/test/java/com/anhtester/listeners/AnnotationTransformer.java, it programmatically sets the retry analyzer during TestNG's annotation processing phase, ensuring consistent retry behavior across all tests while keeping test classes clean.
Can I disable retries entirely?
Yes. Set RETRY_TEST_FAIL = 0 in the properties file. When maxTry parses to 0, the Retry.retry() method will never enter the retry loop because count < maxTry evaluates to false immediately, effectively disabling the retry mechanism.
Where is the retry logic actually executed?
The retry decision logic resides in src/test/java/com/anhtester/listeners/Retry.java within the retry(ITestResult result) method. This method is invoked by TestNG's runner each time a test fails, checking the attempt counter against the configured maximum before deciding whether to schedule another execution.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →