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
相关产品推荐
相关产品推荐

