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:

  1. Initialization: FrameworkConstants loads all properties files via PropertiesHelpers.loadAllFiles() in its static initializer
  2. Annotation Processing: As TestNG parses the suite XML, AnnotationTransformer.transform() executes for every test method, assigning Retry.class as the retry analyzer
  3. Failure Detection: When a test fails, TestNG invokes Retry.retry(ITestResult)
  4. Retry Decision: If the internal counter is less than maxTry (parsed from RETRY_TEST_FAIL), the method increments the counter and returns true, triggering a re-run
  5. Final Status: Once the maximum retry count is reached, the method returns false and the test is marked as finally failed

This approach ensures zero changes to individual test classes while providing centralized control over retry behavior.

Summary

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →