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

Selenium Java实现WebDriver线程安全 解决并行测试失败问题

解决方案

你的问题核心是没有正确用ThreadLocal管理WebDriver的线程隔离——虽然创建了ThreadLocal实例,但依然在使用全局的driver变量,导致多线程共享同一个WebDriver实例,并行运行时互相干扰。

以下是完整的修正方案:

1. 修改BaseClass,用ThreadLocal完全管理WebDriver

把原来的全局driver替换为ThreadLocal实例,所有操作都通过ThreadLocal来获取和销毁WebDriver:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import io.github.bonigarcia.wdm.WebDriverManager;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.Duration;
import java.util.Properties;

public class BaseClass {
    // 用ThreadLocal存储WebDriver,保证每个线程有独立实例
    private ThreadLocal<WebDriver> threadSafeDriver = new ThreadLocal<>();
    public HomePage homePage;

    public WebDriver setup() throws IOException {
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream(
                System.getProperty("user.dir") + "\\src\\main\\resource\\GlobalData.Properties");
        prop.load(fis);
        String browserName = System.getProperty("browser") != null ? System.getProperty("browser")
                : prop.getProperty("browser");

        WebDriver driver = null;
        if (browserName.contains("chrome")) {
            WebDriverManager.chromedriver().setup();
            driver = new ChromeDriver();
        } else if (browserName.contains("edge")) {
            WebDriverManager.edgedriver().setup();
            driver = new EdgeDriver();
        } else if (browserName.contains("firefox")) {
            WebDriverManager.firefoxdriver().setup();
            driver = new FirefoxDriver();
        }
        
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
        driver.manage().window().maximize();
        // 将当前线程的driver存入ThreadLocal
        threadSafeDriver.set(driver);
        return threadSafeDriver.get();
    }

    @BeforeMethod
    public HomePage LaunchApplication() throws IOException {
        // 从ThreadLocal获取当前线程的driver
        WebDriver driver = setup();
        homePage = new HomePage(driver);
        homePage.goTo();
        return homePage;
    }

    @AfterMethod
    public void tearDown() {
        // 获取当前线程的driver并关闭
        WebDriver driver = threadSafeDriver.get();
        if (driver != null) {
            driver.quit(); // 用quit而不是close,确保彻底销毁浏览器进程
            // 移除ThreadLocal中的实例,避免内存泄漏
            threadSafeDriver.remove();
        }
    }
}

2. 确保TestNG的并行配置正确

在testng.xml里配置方法级并行,指定线程数:

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Test Suite" parallel="methods" thread-count="3">
    <test name="All Tests">
        <classes>
            <class name="com.yourpackage.TestCases"/>
        </classes>
    </test>
</suite>

关键修改点说明

  • 移除了全局的public WebDriver driver,改用ThreadLocal<WebDriver>存储每个线程独立的WebDriver实例
  • setup方法中创建driver后,通过threadSafeDriver.set(driver)绑定到当前线程
  • 所有需要使用driver的地方,都通过threadSafeDriver.get()获取当前线程的实例
  • tearDown中不仅关闭浏览器,还调用threadSafeDriver.remove()清理ThreadLocal,避免内存泄漏
  • 把driver.close()改为driver.quit(),确保浏览器进程完全终止,避免残留进程影响并行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 05:46:09