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

ExtentReport的@AfterMethod块触发NullPointerException问题求助

解决ExtentReport @AfterMethod中的NullPointerException问题

你的空指针异常根源非常明确:logger对象从未被初始化。你在类中声明了public ExtentTest logger;,但全程没有通过extent.startTest()为它创建实例,导致在@AfterMethod里调用logger.log()时,logger仍为null,直接触发了空指针异常。

修复步骤

  • 在每个@Test方法的开头,调用extent.startTest()初始化logger,传入当前测试方法的名称,让日志和测试用例关联起来;
  • 确保@AfterMethod中使用的logger是已完成初始化的实例。

修改后的完整代码

package com.cna.qa.testcases;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;

import junit.framework.Assert;

public class VerifyTitle {
    public ExtentReports extent;
    public ExtentTest logger;
    public WebDriver driver;

    @BeforeTest
    public void beforetest() {
        extent = new ExtentReports("C:\\Users\\mm\\selenium_projects\\SmokeTest\\output\\extentReport.html", true);
    }

    @Test
    public void verifyBlogTitle1() {
        // 初始化logger,绑定当前测试用例
        logger = extent.startTest("verifyBlogTitle1");
        
        System.setProperty("webdriver.gecko.driver", "C:\\Users\\mmia\\IdeaProjects\\geckoDriver\\geckodriver.exe");
        driver = new FirefoxDriver();
        driver.manage().window().maximize();
        driver.get("https://devxx.yyy.net");
        String title = driver.getTitle();
        Assert.assertTrue(title.contains("Dashboard"));
        
        // 可选:在测试过程中添加步骤日志
        logger.log(LogStatus.INFO, "已导航至目标URL并验证页面标题");
    }

    public static String screenshot(WebDriver driver, String screenshotname) throws IOException {
        String dtname = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date());
        TakesScreenshot ts = (TakesScreenshot) driver;
        File source = ts.getScreenshotAs(OutputType.FILE);
        String destination = System.getProperty("user.dir") + "\\screenshots\\" + screenshotname + "_" + dtname + ".png";
        File finalDestination = new File(destination);
        FileUtils.copyFile(source, finalDestination);
        return destination;
    }

    @AfterMethod()
    public void teardown(ITestResult result) throws IOException {
        if (result.getStatus() == ITestResult.SUCCESS) {
            System.out.println(result.getStatus());
            logger.log(LogStatus.PASS, result.getName() + " 执行通过");
        } else if (result.getStatus() == ITestResult.FAILURE) {
            logger.log(LogStatus.FAIL, "失败测试用例名称:" + result.getName());
            logger.log(LogStatus.FAIL, "失败原因:" + result.getThrowable());
            String screenshotPath = VerifyTitle.screenshot(driver, result.getName());
            // 修正截图日志写法,让报告中直接展示截图而非仅路径
            logger.log(LogStatus.FAIL, logger.addScreenCapture(screenshotPath));
        } else if (result.getStatus() == ITestResult.SKIP) {
            logger.log(LogStatus.SKIP, "跳过测试用例名称:" + result.getName());
        }
        extent.endTest(logger);
        driver.quit();
    }

    @AfterTest
    public void aftertest() {
        extent.flush();
        extent.close();
    }
}

额外提示

  • 如果后续新增多个@Test方法,每个方法都需要在开头初始化logger,保证每个测试用例都有独立的日志实例;
  • 我调整了失败用例的截图日志写法,原来的写法只会在报告中显示路径字符串,改用addScreenCapture()可以让报告直接嵌入截图,更直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:33:21