You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TestNG:二次或三次重跑通过后测试脚本状态及统计异常问题

解决TestNG中IRetryAnalyzer重跑导致测试计数异常的问题

问题根源

IRetryAnalyzer仅负责触发失败测试的重跑逻辑,但TestNG默认会将每一次重跑都视为独立的测试用例统计。比如测试在第3次尝试通过时,系统会显示总执行3次,虽然最终结果里的Total run:1是实际测试用例数,但统计计数会出现混淆。

解决方案

通过结合IAnnotationTransformer(全局绑定重试逻辑)和IReporter(自定义统计逻辑),修正统计结果,避免重跑次数干扰真实测试用例计数。

1. 实现IRetryAnalyzer基础重试类

import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;

public class RetryAnalyzer implements IRetryAnalyzer {
    private int retryCount = 0;
    private static final int MAX_RETRY = 2; // 最多重跑2次,总计3次尝试

    @Override
    public boolean retry(ITestResult result) {
        if (retryCount < MAX_RETRY) {
            retryCount++;
            return true;
        }
        return false;
    }
}

2. 用IAnnotationTransformer全局绑定重试

避免在每个测试方法上手动添加@Test(retryAnalyzer = ...)注解:

import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class RetryTransformer implements IAnnotationTransformer {
    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
        annotation.setRetryAnalyzer(RetryAnalyzer.class);
    }
}

3. 实现IReporter自定义统计逻辑

重写统计逻辑,将重跑的测试合并为一次计数:

import org.testng.IReporter;
import org.testng.ISuite;
import org.testng.ISuiteResult;
import org.testng.ITestContext;
import org.testng.xml.XmlSuite;
import java.util.List;
import java.util.Map;

public class CustomTestReporter implements IReporter {
    @Override
    public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDir) {
        for (ISuite suite : suites) {
            Map<String, ISuiteResult> suiteResults = suite.getResults();
            for (ISuiteResult result : suiteResults.values()) {
                ITestContext context = result.getTestContext();
                
                // 统计真实的测试用例数(去重重跑记录)
                int totalTests = context.getAllTestMethods().length;
                long failedTests = context.getFailedTests().getAllResults().stream()
                        .filter(res -> !res.isSuccess())
                        .map(res -> res.getMethod().getMethodName())
                        .distinct()
                        .count();
                long skippedTests = context.getSkippedTests().getAllResults().stream()
                        .map(res -> res.getMethod().getMethodName())
                        .distinct()
                        .count();
                long passedTests = totalTests - failedTests - skippedTests;

                // 输出修正后的统计数据
                System.out.println("=== 修正后测试统计 ===");
                System.out.printf("Total run: %d%n", totalTests);
                System.out.printf("Passed: %d%n", passedTests);
                System.out.printf("Failed: %d%n", failedTests);
                System.out.printf("Skipped: %d%n", skippedTests);
            }
        }
    }
}

4. 在testng.xml中配置监听器

将Transformer和自定义Reporter加入配置:

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="RetryTestSuite">
    <listeners>
        <listener class-name="com.yourpackage.RetryTransformer"/>
        <listener class-name="com.yourpackage.CustomTestReporter"/>
    </listeners>
    <test name="CoreTests">
        <classes>
            <class name="com.yourpackage.YourTestClass"/>
        </classes>
    </test>
</suite>

补充说明

  • 上述配置后,自定义报告将按真实测试用例数统计,不会把重跑次数计入总执行数。
  • 若使用TestNG自带HTML报告,可修改报告模板或结合ExtentReports等第三方工具,更优雅地展示重跑后的测试结果。

内容的提问来源于stack exchange,提问作者qadhava sharath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 20:24:32