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

Extent Report测试步骤日志失效:多方法TestNG用例报空指针异常求助

解决方案:解决Extent Report在业务类中写日志的NullPointerException问题

问题根源

你在主测试类中创建了ExtentTest实例(也就是代码里的logger),但你的业务类(比如loginPage、ReportFormattingPage)并没有获取到这个实例的引用,当你在这些类的方法里尝试调用logger.log()时,自然会抛出空指针异常。

步骤1:修改业务类,添加ExtentTest引用并提供设置方法

以loginPage为例,修改它的代码,添加ExtentTest成员变量,并提供setter方法来接收这个实例:

import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.By;

public class loginPage {
    private WebDriver driver;
    private ExtentTest logger; // 添加ExtentTest成员
    private String username = "your_username"; // 替换为实际用户名
    private String password = "your_password"; // 替换为实际密码

    // 原构造方法保留,用于初始化driver
    public loginPage(WebDriver driver) {
        this.driver = driver;
    }

    // 添加setter方法,用于后续传入logger实例
    public void setLogger(ExtentTest logger) {
        this.logger = logger;
    }

    public void LoginToClient() {
        // 现在可以正常写入Extent Report日志了
        logger.log(LogStatus.INFO, "开始执行登录操作:输入用户名");
        driver.findElement(By.id("username")).sendKeys(username);
        
        logger.log(LogStatus.INFO, "输入登录密码");
        driver.findElement(By.id("password")).sendKeys(password);
        
        logger.log(LogStatus.INFO, "点击登录按钮");
        driver.findElement(By.id("loginBtn")).click();
    }
}

其他业务类(比如ReportFormattingPage)也按照同样的方式修改,添加ExtentTest成员和setter方法。

步骤2:在主测试类中为每个测试方法初始化ExtentTest,并传递给业务类

在主测试类中添加@BeforeMethod注解的方法,为每个测试方法创建独立的ExtentTest实例,并把它传递给所有业务类:

import java.lang.reflect.Method;
import org.testng.annotations.BeforeMethod;

// 在你的ReportFormatting类中添加这个方法
@BeforeMethod
public void initTestLogger(Method method) {
    // 为当前测试方法创建ExtentTest实例,用方法名作为测试名称
    logger = extent.startTest(method.getName());
    
    // 将logger传递给所有业务类
    login.setLogger(logger);
    reportFormattingPage.setLogger(logger);
    logout.setLogger(logger);
    createContentMenuButton.setLogger(logger);
    // 其他业务类也依次设置
}

步骤3:修复@BeforeTest的执行顺序问题

你的代码中有两个@BeforeTest方法,TestNG会按方法名字母顺序执行,这可能导致extent还没初始化就创建了业务类。给它们设置优先级,确保setExtent先执行:

@BeforeTest(priority = 1)
public void setExtent(){
    extent = new ExtentReports(System.getProperty("user.dir")+"/test-output/ExtentReport.html", true);
    extent.addSystemInfo("Host Name", "Calcutta");
    extent.addSystemInfo("User Name", "Admin");
    extent.addSystemInfo("Environment", "QA");
}

@Parameters({ "yellowfinURL" })
@BeforeTest(priority = 2, enabled = true)
public void instantiatePages(String url) {
    driver.get(url);
    login = new loginPage(driver);
    logout = new Logout(driver);
    createContentMenuButton = new ContentMenuButton(driver);
    reportView = new ViewForReport(driver);
    createChart = new ReportChartBuilder(driver);
    ps = new Printscreen(driver);
    reportFormattingPage = new ReportFormattingPage(driver);
}

步骤4:完善@AfterMethod和添加@AfterTest方法

确保在@AfterMethod中结束当前测试,并在@AfterTest中刷新和关闭Extent Report:

import org.testng.ITestResult;
import java.io.IOException;

@AfterMethod(alwaysRun=true)
public void TearDown_AM(ITestResult result) throws IOException {
    System.out.println("@After Method");
    try {
        if(result.getStatus()==ITestResult.FAILURE) {
            String screenshotPath = Screenshots.getScreenshot(driver, result.getName());
            String image= logger.addScreenCapture(screenshotPath);
            System.out.println(image);
            String TestCaseName = this.getClass().getSimpleName() + " Test Case Failure and Title/Boolean Value Failed";
            logger.log(LogStatus.FAIL, TestCaseName);
        } else if(result.getStatus()==ITestResult.SUCCESS) {
            logger.log(LogStatus.PASS, "测试方法 " + result.getName() + " 执行成功");
        } else if(result.getStatus()==ITestResult.SKIP) {
            logger.log(LogStatus.SKIP, "测试方法 " + result.getName() + " 被跳过");
        }
        // 结束当前测试的ExtentTest实例
        extent.endTest(logger);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@AfterTest
public void finishExtentReport() {
    // 刷新报告,确保所有日志都写入文件
    extent.flush();
    // 关闭报告对象
    extent.close();
}

步骤5:在@Test方法中正常调用业务方法

现在你在@Test方法中调用业务类的方法时,日志就能正常写入Extent Report了:

@Test
public void TestOne() {
    // 这里不需要再创建logger,@BeforeMethod已经初始化好了
    login.LoginToClient();
    reportFormattingPage.AccessMainPage();
    // 其他测试操作
}

这样修改后,你的业务类中的日志代码就不会再抛出NullPointerException,所有测试步骤的日志都会被正确记录到Extent Report中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:38:42