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(); } } }
问题分析
- ThreadLocal使用逻辑冗余:
createLocalDriver方法开头调用quitDriver(),会先销毁当前线程的WebDriver实例再重新创建,既造成资源浪费,也可能在并行场景下引发线程间实例干扰。 - 测试框架并行配置缺失:若未在TestNG、Cucumber等测试框架中开启并行执行模式,所有测试用例会默认在同一线程运行,自然共用同一个浏览器实例。
- 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
相关产品推荐
相关产品推荐

