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

TestNG与Selenium并行测试中如何正确调用driver.quit()?

问题:TestNG并行测试中仅一个浏览器窗口被关闭,其余需手动关闭

我正在使用TestNG和Selenium运行4个并行测试,测试能正常同时打开4个浏览器窗口运行,但存在测试无法结束的问题:@AfterTest代码块仅触发一次,仅一个窗口关闭,其余窗口需手动关闭。请问如何让每个测试完成后都关闭对应的driver?

我的代码

Java测试类

public class SecondNGTest {
    public static WebDriver driver;
    public static ChromeOptions chromeOptions;
    public static final String USERNAME = "PRIVATE";
    public static final String AUTOMATE_KEY = "PRIVATE";
    public static final String URL = "https://" + USERNAME + ":" + AUTOMATE_KEY + "@hub-cloud.browserstack.com/wd/hub";
    public static DesiredCapabilities caps;

    @Test
    public void executSessionOne() throws MalformedURLException{
        //First session of WebDriver
        caps = new DesiredCapabilities();
        caps.setCapability("os", "Windows");
        caps.setCapability("os_version", "10");
        caps.setCapability("browser", "Chrome");
        caps.setCapability("browser_version", "80.0 beta");
        caps.setCapability("browserstack.local", "false");
        caps.setCapability("browserstack.selenium_version", "3.5.2");
        caps.setCapability("name", "selenium test");
        driver = new RemoteWebDriver(new URL(URL), caps);
        chromeOptions = new ChromeOptions();
        String chromeDriverPath = "resources/chromedriver.exe";
        System.setProperty("webdriver.chrome.driver", chromeDriverPath);
        //Goto guru99 site
        driver.get("http://google.com/");
    }

    @Test
    public void executeSessionTwo() throws MalformedURLException{
        //Second session of WebDriver
        caps = new DesiredCapabilities();
        caps.setCapability("os", "Windows");
        caps.setCapability("os_version", "10");
        caps.setCapability("browser", "Chrome");
        caps.setCapability("browser_version", "80.0 beta");
        caps.setCapability("browserstack.local", "false");
        caps.setCapability("browserstack.selenium_version", "3.5.2");
        caps.setCapability("name", "selenium test");
        driver = new RemoteWebDriver(new URL(URL), caps);
        chromeOptions = new ChromeOptions();
        String chromeDriverPath = "resources/chromedriver.exe";
        System.setProperty("webdriver.chrome.driver", chromeDriverPath);
        //Goto guru99 site
        driver.get("http://youtube.com/");
    }

    @Test
    public void executSessionThree() throws MalformedURLException{
        //Third session of WebDriver
        caps = new DesiredCapabilities();
        caps.setCapability("os", "Windows");
        caps.setCapability("os_version", "10");
        caps.setCapability("browser", "Chrome");
        caps.setCapability("browser_version", "80.0 beta");
        caps.setCapability("browserstack.local", "false");
        caps.setCapability("browserstack.selenium_version", "3.5.2");
        caps.setCapability("name", "selenium test");
        driver = new RemoteWebDriver(new URL(URL), caps);
        chromeOptions = new ChromeOptions();
        String chromeDriverPath = "resources/chromedriver.exe";
        System.setProperty("webdriver.chrome.driver", chromeDriverPath);
        //Goto guru99 site
        driver.get("http://slack.com/");
    }

    @Test
    public void executSessionFour() throws MalformedURLException{
        //Third session of WebDriver
        caps = new DesiredCapabilities();
        caps.setCapability("os", "Windows");
        caps.setCapability("os_version", "10");
        caps.setCapability("browser", "Chrome");
        caps.setCapability("browser_version", "80.0 beta");
        caps.setCapability("browserstack.local", "false");
        caps.setCapability("browserstack.selenium_version", "3.5.2");
        caps.setCapability("name", "selenium test");
        driver = new RemoteWebDriver(new URL(URL), caps);
        chromeOptions = new ChromeOptions();
        String chromeDriverPath = "resources/chromedriver.exe";
        System.setProperty("webdriver.chrome.driver", chromeDriverPath);
        //Goto guru99 site
        driver.get("http://yahoo.com/");
    }

    @AfterTest
    public void browserclose (){
        driver.quit();
        System.out.println("TestCase : Browser was closed");
    }
}

testng.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="TestSuite" >
    <test name="testGuru" thread-count="4" parallel="methods">
        <classes>
            <class name="selerixautomation.SecondNGTest">
            </class>
        </classes>
    </test>
</suite>

解决方案

这个问题我之前帮不少开发者解决过,核心是对TestNG注解生命周期和并行测试变量作用域的理解偏差,咱们一步步修正:

1. 换用正确的TestNG注解

  • @AfterTest:在整个<test>标签下的所有测试方法执行完成后仅运行一次,这就是为什么只有一个窗口被关闭的原因。
  • @AfterMethod:在每个@Test方法执行完成后都会运行一次,完美匹配你每个测试方法对应一个浏览器窗口的场景。

2. 修正变量作用域

你把driver、caps等变量声明为static,这会导致多个并行线程共享同一个变量实例,后面的线程会覆盖前面的driver引用,最终只有最后一个driver被关闭。所以要移除static修饰符,让每个测试方法拥有独立的driver实例。

3. 移除冗余配置

你用的是RemoteWebDriver连接BrowserStack云端hub,完全不需要设置webdriver.chrome.driver系统属性(这是本地运行ChromeDriver才需要的),这部分代码是多余的,直接删掉即可。

4. 优化代码复用

把重复的DesiredCapabilities配置逻辑抽成公共方法,避免代码冗余,也方便后续统一修改配置。

修改后的完整代码

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.net.URL;

public class SecondNGTest {
    private WebDriver driver;
    private static final String USERNAME = "PRIVATE";
    private static final String AUTOMATE_KEY = "PRIVATE";
    private static final String URL = "https://" + USERNAME + ":" + AUTOMATE_KEY + "@hub-cloud.browserstack.com/wd/hub";

    // 公共方法:创建并返回统一的BrowserStack配置
    private DesiredCapabilities getBrowserStackCaps() {
        DesiredCapabilities caps = new DesiredCapabilities();
        caps.setCapability("os", "Windows");
        caps.setCapability("os_version", "10");
        caps.setCapability("browser", "Chrome");
        caps.setCapability("browser_version", "80.0 beta");
        caps.setCapability("browserstack.local", "false");
        caps.setCapability("browserstack.selenium_version", "3.5.2");
        caps.setCapability("name", "selenium test");
        return caps;
    }

    @Test
    public void executSessionOne() throws MalformedURLException {
        driver = new RemoteWebDriver(new URL(URL), getBrowserStackCaps());
        driver.get("http://google.com/");
    }

    @Test
    public void executeSessionTwo() throws MalformedURLException {
        driver = new RemoteWebDriver(new URL(URL), getBrowserStackCaps());
        driver.get("http://youtube.com/");
    }

    @Test
    public void executSessionThree() throws MalformedURLException {
        driver = new RemoteWebDriver(new URL(URL), getBrowserStackCaps());
        driver.get("http://slack.com/");
    }

    @Test
    public void executSessionFour() throws MalformedURLException {
        driver = new RemoteWebDriver(new URL(URL), getBrowserStackCaps());
        driver.get("http://yahoo.com/");
    }

    // 替换@AfterTest为@AfterMethod,每个测试方法结束后关闭对应driver
    @AfterMethod
    public void browserClose() {
        if (driver != null) { // 增加空判断,避免异常
            driver.quit();
            System.out.println("TestCase : Browser was closed");
        }
    }
}

保持testng.xml不变

你的testng.xml配置是正确的,parallel="methods"和thread-count="4"可以让4个测试方法并行执行,不需要修改。

这样修改后,每个测试方法执行完成后,对应的@AfterMethod都会触发,关闭当前方法的driver实例,所有浏览器窗口都会被自动关闭啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 20:22:58