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

Selenium并行测试无法运行:单浏览器执行所有测试致用例失败

测试用例并行执行失败:多用例共用单一浏览器实例的解决方法

已配置Driver Hook初始化WebDriver,期望实现测试用例并行执行,但目前仅启动一个浏览器,所有测试操作都在该浏览器中运行,导致测试用例执行失败。相关Driver Hook代码如下:

public class DriverHooks {
    private static final String homeDirPath = System.getProperty("user.dir");

    public static ThreadLocal<WebDriver> webdriver = new ThreadLocal<>();

    public static WebDriver getDriver() {
        if (webdriver.get() == null) {
            createLocalDriver();
        }
        return webdriver.get();
    }

    public static void setupDriver() {
        if (webdriver.get() == null) {
            createLocalDriver();
        }
    }

    private static void createLocalDriver() {
        try {
            quitDriver();
            if (webdriver.get() == null) {
                String downloadFilepath = homeDirPath + FileGetParams.paramLookUp("downloadsPath");
                LogAndErrorHandler.Instance().LogInfo(downloadFilepath);
                switch (FileGetParams.paramLookUp("BROWSER").toUpperCase()) {
                  
                    case "EDGE":
                    case "CHROME":
                        ChromeOptions chromeOptions = new ChromeOptions();
                        chromeOptions.setExperimentalOption("prefs",
                                new HashMap<String, Object>() {{
                                    put("permissions.default.camera", 1);
                                }}
                        );
                        if (System.getenv("WINDOW_SIZE") != null)
                            chromeOptions.addArguments(System.getenv("WINDOW_SIZE"));
                        else chromeOptions.addArguments("--start-maximized");
                        WebDriverManager.chromedriver().setup();
                        try {
                            webdriver.set(new ChromeDriver(chromeOptions));
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        }
                        break;
                }
                if (webdriver.get() != null) {
                    webdriver.get().manage().deleteAllCookies();
                }
            }
        } catch (Exception e) {
            LogAndErrorHandler.Instance().LogError(e.getMessage());
        }
    }

    public static void quitDriver() {
        if (webdriver.get() != null) {
            webdriver.get().quit();
            webdriver.remove();
        }
    }
}

问题分析

  1. ThreadLocal使用逻辑冗余:createLocalDriver方法开头调用quitDriver(),会先销毁当前线程的WebDriver实例再重新创建,既造成资源浪费,也可能在并行场景下引发线程间实例干扰。
  2. 测试框架并行配置缺失:若未在TestNG、Cucumber等测试框架中开启并行执行模式,所有测试用例会默认在同一线程运行,自然共用同一个浏览器实例。
  3. Hook执行时机错误:若Driver Hook仅在全局初始化一次(而非每个测试用例/线程执行前初始化),会导致所有用例复用同一个实例。

解决方案

1. 修复DriverHooks代码

移除createLocalDriver开头的quitDriver()调用,保留线程隔离特性的同时避免不必要的实例销毁:

public class DriverHooks {
    private static final String homeDirPath = System.getProperty("user.dir");
    public static ThreadLocal<WebDriver> webdriver = new ThreadLocal<>();

    public static WebDriver getDriver() {
        if (webdriver.get() == null) {
            createLocalDriver();
        }
        return webdriver.get();
    }

    public static void setupDriver() {
        if (webdriver.get() == null) {
            createLocalDriver();
        }
    }

    private static void createLocalDriver() {
        try {
            if (webdriver.get() == null) {
                String downloadFilepath = homeDirPath + FileGetParams.paramLookUp("downloadsPath");
                LogAndErrorHandler.Instance().LogInfo(downloadFilepath);
                switch (FileGetParams.paramLookUp("BROWSER").toUpperCase()) {
                    case "EDGE":
                    case "CHROME":
                        ChromeOptions chromeOptions = new ChromeOptions();
                        chromeOptions.setExperimentalOption("prefs",
                                new HashMap<String, Object>() {{
                                    put("permissions.default.camera", 1);
                                }}
                        );
                        if (System.getenv("WINDOW_SIZE") != null)
                            chromeOptions.addArguments(System.getenv("WINDOW_SIZE"));
                        else chromeOptions.addArguments("--start-maximized");
                        WebDriverManager.chromedriver().setup();
                        try {
                            webdriver.set(new ChromeDriver(chromeOptions));
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        }
                        break;
                }
                if (webdriver.get() != null) {
                    webdriver.get().manage().deleteAllCookies();
                }
            }
        } catch (Exception e) {
            LogAndErrorHandler.Instance().LogError(e.getMessage());
        }
    }

    public static void quitDriver() {
        if (webdriver.get() != null) {
            webdriver.get().quit();
            webdriver.remove();
        }
    }
}

2. 开启测试框架并行配置

TestNG配置示例

在testng.xml中设置并行执行模式:

<suite name="TestSuite" parallel="methods" thread-count="5">
    <!-- 测试类/测试方法配置 -->
</suite>
  • parallel="methods":按测试方法并行执行
  • thread-count="5":设置并行线程数

Cucumber配置示例(Maven)

在pom.xml的Surefire插件中开启并行:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M7</version>
    <configuration>
        <parallel>methods</parallel>
        <threadCount>5</threadCount>
        <includes>
            <include>**/RunCucumberTest.java</include>
        </includes>
    </configuration>
</plugin>

3. 配置Hook执行时机

确保每个测试用例执行前初始化Driver,执行后销毁实例:

TestNG Hook示例

public class TestHooks {
    @BeforeMethod
    public void beforeTest() {
        DriverHooks.setupDriver();
    }

    @AfterMethod
    public void afterTest() {
        DriverHooks.quitDriver();
    }
}

Cucumber Hook示例

public class CucumberHooks {
    @Before
    public void beforeScenario() {
        DriverHooks.setupDriver();
    }

    @After
    public void afterScenario() {
        DriverHooks.quitDriver();
    }
}

总结

ThreadLocal本身已保证每个线程拥有独立的WebDriver实例,核心问题在于测试框架未开启并行配置,或Hook执行时机不正确。通过修复代码冗余逻辑、开启并行配置、设置正确的Hook时机,即可实现测试用例的并行执行,每个用例拥有独立的浏览器实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 19:51:00