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

如何使用Extent Reports生成包含类及对应测试用例的测试报告

如何用Extent Reports生成带测试类-测试用例层级的TestNG测试报告

我来帮你一步步实现这个需求——基于你现有的TestNG配置,生成能清晰展示测试类及其下属测试用例层级结构的Extent Reports。

第一步:确保Extent Reports依赖正确

首先要在你的项目中引入Extent Reports和TestNG的兼容依赖,以Maven为例,在pom.xml中添加:

<dependencies>
    <!-- TestNG -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.8.0</version>
        <scope>test</scope>
    </dependency>
    <!-- Extent Reports TestNG Adapter -->
    <dependency>
        <groupId>com.aventstack</groupId>
        <artifactId>extentreports-testng-adapter</artifactId>
        <version>5.0.9</version>
    </dependency>
    <!-- 核心Extent Reports库 -->
    <dependency>
        <groupId>com.aventstack</groupId>
        <artifactId>extentreports</artifactId>
        <version>5.0.9</version>
    </dependency>
</dependencies>

注意:版本号请保持一致,避免兼容性问题。

第二步:实现自定义TestNG监听器CustomExtentReporter

你的testng.xml已经配置了这个监听器,现在需要完善它的逻辑,核心是将测试类作为父节点,测试用例作为子节点关联到Extent Reports中。

import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.reporter.ExtentSparkReporter;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

import java.util.HashMap;
import java.util.Map;

public class CustomExtentReporter implements ITestListener {
    // 核心报告对象
    private ExtentReports extent;
    // 存储测试类对应的父节点,避免重复创建
    private Map<String, ExtentTest> classTestMap = new HashMap<>();

    @Override
    public void onStart(ITestContext context) {
        // 初始化SparkReporter(生成美观的HTML报告)
        ExtentSparkReporter sparkReporter = new ExtentSparkReporter("test-output/extent-report.html");
        // 配置报告标题、主题等
        sparkReporter.config().setDocumentTitle("自动化测试报告");
        sparkReporter.config().setReportName("测试类-用例层级报告");
        
        // 初始化ExtentReports并关联Reporter
        extent = new ExtentReports();
        extent.attachReporter(sparkReporter);
        // 添加系统信息(可选)
        extent.setSystemInfo("环境", context.getCurrentXmlTest().getParameter("nodeURL"));
        extent.setSystemInfo("TestNG版本", "7.8.0");
    }

    @Override
    public void onTestStart(ITestResult result) {
        // 获取当前测试方法所属的类名称
        String className = result.getTestClass().getName();
        // 获取测试用例名称
        String methodName = result.getMethod().getMethodName();
        
        // 如果该类还没有父节点,创建一个
        ExtentTest classTest = classTestMap.computeIfAbsent(className, 
            key -> extent.createTest(className));
        
        // 创建测试用例作为类节点的子节点,并关联到当前结果
        ExtentTest methodTest = classTest.createNode(methodName);
        result.setAttribute("extentTest", methodTest);
    }

    @Override
    public void onTestSuccess(ITestResult result) {
        // 获取当前测试用例的ExtentTest对象
        ExtentTest methodTest = (ExtentTest) result.getAttribute("extentTest");
        if (methodTest != null) {
            methodTest.log(Status.PASS, "测试用例执行成功");
        }
    }

    @Override
    public void onTestFailure(ITestResult result) {
        ExtentTest methodTest = (ExtentTest) result.getAttribute("extentTest");
        if (methodTest != null) {
            methodTest.log(Status.FAIL, "测试用例执行失败:" + result.getThrowable().getMessage());
            // 可选:添加失败截图
            // methodTest.addScreenCaptureFromPath("screenshot-path.png");
        }
    }

    @Override
    public void onTestSkipped(ITestResult result) {
        ExtentTest methodTest = (ExtentTest) result.getAttribute("extentTest");
        if (methodTest != null) {
            methodTest.log(Status.SKIP, "测试用例被跳过:" + result.getSkipCausedBy().getMessage());
        }
    }

    @Override
    public void onFinish(ITestContext context) {
        // 必须调用flush()才能生成最终报告
        if (extent != null) {
            extent.flush();
        }
    }
}

第三步:测试类示例(以你的com.org.web.Home为例)

写一个简单的测试类,包含多个测试用例,验证层级结构:

package com.org.web;

import org.testng.annotations.Test;

public class Home {
    @Test
    public void testHomePageTitle() {
        // 测试逻辑:验证首页标题
        System.out.println("执行testHomePageTitle");
    }

    @Test
    public void testHomePageNavigation() {
        // 测试逻辑:验证首页导航
        System.out.println("执行testHomePageNavigation");
    }

    @Test(enabled = false)
    public void testHomePageSearch() {
        // 测试逻辑:验证首页搜索
        System.out.println("执行testHomePageSearch");
    }
}

第四步:运行TestNG并查看报告

  1. 运行你的testng.xml配置文件
  2. 打开test-output/extent-report.html文件,你会看到:
    • 顶部统计所有测试类和用例的状态
    • 左侧导航栏按测试类分组,点击类名可以展开下属的所有测试用例
    • 每个测试用例的执行状态(通过/失败/跳过)和详细日志都清晰展示

关键注意事项

  • 确保CustomExtentReporter的全类名在testng.xml中配置正确,比如你的配置里com.org.CustomExtentReporter要和实际类路径一致
  • 不要忘记在onFinish方法中调用extent.flush(),否则报告不会生成
  • 如果需要添加截图、日志等额外信息,可以在对应的测试结果方法中扩展逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:11:33