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

如何解决Java Selenium TestNG按分组执行时的空指针异常?

TestNG分组运行时WebDriver空指针异常问题

问题描述

当通过TestNG XML执行所有测试用例时全部成功,但通过分组运行时抛出空指针异常。
错误信息:java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebDriver.get(String)" because the return value of "org.testpackage.TC370_Quiz.getDriver()" is null

用户提供的代码片段

BaseClass代码

public class BaseClass {

    public ThreadLocal<WebDriver> driver = new ThreadLocal<>();

    public void setDriver(WebDriver driver) {
        this.driver.set(driver);
    }

    public WebDriver getDriver() {
        return this.driver.get();
    }

    // 创建ReadConfig实例
    ReadConfig readconfig = new ReadConfig();

    // 获取应用URL
    public String baseURL = readconfig.getApplicationUrl();

    // 启动浏览器
    @Parameters("browser")
    @BeforeMethod
    public void launch(ITestContext context, @Optional("chrome") String browser, Method method)
                throws MalformedURLException {
        if (browser.equalsIgnoreCase("chrome")) {
            ChromeOptions options = new ChromeOptions();
            setDriver(new ChromeDriver(options));
        }
    }
}

页面类(QuizPage)代码

public class QuizPage extends BaseClass {

    WebDriver driver;

    public QuizPage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }

    @FindBy(xpath = "//label[text()='Quiz']")
    private WebElement sQuiz;
}

页面对象管理器(PageObjectManager)代码

public class PageObjectManager {
    public QuizPage quizPage;

    public QuizPage getQuizPage(WebDriver driver) {
        return (quizPage == null) ? quizPage = new QuizPage(driver) : quizPage;
    }
}

测试类代码

@Test(priority = 377, groups = {"smoke"}, enabled = true)
public void testingOnStartButtonInHindiInstructionPage() throws InterruptedException {

    getDriver().get(baseURL);
    extentTest.info("Website launched");

    PageObjectManager pom = new PageObjectManager();

    pom.getResources(getDriver()).mouseHoverOnResources();

    pom.getQuizPage(getDriver()).clickQuiz();
    extentTest.info("Clicked quiz");
}

TestNG XML配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="false" thread-count="2">
<parameter name="author" value="Jey" />

<test name="Test" parallel="classes" thread-count="1" enabled="true">
    <parameter name="browser" value="chrome"></parameter>
    <groups>
        <run>
            <include name="smoke"></include>
        </run>
        </groups>
    <classes>
        <class name="org.testpackage.TC370_Quiz"></class>
    </classes>
</test>
</suite> 

问题根源分析

  1. @BeforeMethod执行异常:分组运行时,TestNG可能未正确触发@BeforeMethod,导致ThreadLocal<WebDriver>未初始化。原方法参数过多(ITestContext、Method)可能影响TestNG在分组模式下的参数传递逻辑。
  2. 页面类冗余WebDriver变量:QuizPage继承BaseClass后重复声明WebDriver driver,覆盖了父类的ThreadLocal驱动实例,导致页面初始化时使用的驱动与测试类中getDriver()获取的实例不一致。
  3. POM设计冗余:页面类已继承BaseClass,无需再通过构造方法传递WebDriver实例,增加了代码复杂度和出错概率。

解决方案

1. 简化@BeforeMethod,确保分组运行时执行

修改BaseClass的launch方法,减少不必要的参数,保证驱动初始化逻辑稳定执行:

@Parameters("browser")
@BeforeMethod
public void launch(@Optional("chrome") String browser) throws MalformedURLException {
    WebDriver webDriver;
    if (browser.equalsIgnoreCase("chrome")) {
        ChromeOptions options = new ChromeOptions();
        webDriver = new ChromeDriver(options);
    } else {
        // 其他浏览器初始化逻辑
        webDriver = new FirefoxDriver();
    }
    setDriver(webDriver);
    getDriver().manage().window().maximize();
}

2. 移除页面类冗余WebDriver变量

利用父类的getDriver()方法初始化页面元素:

public class QuizPage extends BaseClass {

    public QuizPage() {
        PageFactory.initElements(getDriver(), this);
    }

    @FindBy(xpath = "//label[text()='Quiz']")
    private WebElement sQuiz;

    public void clickQuiz() {
        sQuiz.click();
    }
}

3. 优化页面对象管理器

无需传递WebDriver参数,直接创建页面实例:

public class PageObjectManager {
    private QuizPage quizPage;

    public QuizPage getQuizPage() {
        return (quizPage == null) ? quizPage = new QuizPage() : quizPage;
    }

    // 其他页面实例方法同理优化
}

4. 更新测试类代码

使用优化后的POM和页面类:

@Test(priority = 377, groups = {"smoke"}, enabled = true)
public void testingOnStartButtonInHindiInstructionPage() throws InterruptedException {
    getDriver().get(baseURL);
    extentTest.info("Website launched");

    PageObjectManager pom = new PageObjectManager();

    pom.getResources().mouseHoverOnResources(); // 假设ResourcesPage已同步优化
    pom.getQuizPage().clickQuiz();
    extentTest.info("Clicked quiz");
}

5. 额外检查点

  • 确认TestNG XML中分组名称无拼写错误;
  • 确保没有其他注解(如@BeforeTest)覆盖@BeforeMethod的执行逻辑;
  • 验证ThreadLocal<WebDriver>在分组运行的线程中被正确初始化和销毁(可添加@AfterMethod关闭驱动)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:46:32