Selenium基于ThreadLocal并行测试出现首个空白浏览器问题如何修复
问题根因
首个浏览器空白的核心问题是WebDriverFactory中静态ThreadLocal实例被反复覆盖,首个测试线程创建的WebDriver实例后续无法被正确访问,导致浏览器没有收到执行指令处于空白状态。
存在的问题点
- 每次调用
setDriver都会创建新的ThreadLocal实例覆盖静态变量,旧ThreadLocal中存储的首个线程WebDriver副本会丢失 setDriver、getDriver添加了不必要的synchronized修饰,既拖慢并行效率,又放大了多线程下实例覆盖的问题closeBrowser销毁driver后没有调用ThreadLocal.remove(),存在内存泄漏,同线程复用场景下还会拿到已销毁的无效driver- 仅Chrome分支调用了
prepareBrowser配置,Firefox启动后没有窗口最大化、超时等配置 - 类设计冗余:
BasePage继承WorldHelper会触发重复初始化WebDriver逻辑,容易拿到空值或错误实例 WorldHelper提前缓存WebDriver实例,若实例化时机早于@Before的setDriver调用,会直接拿到空值
修复代码
1. WebDriverFactory修改
public class WebDriverFactory { // 全局唯一ThreadLocal实例,禁止反复赋值 private static final ThreadLocal<WebDriver> driver = new ThreadLocal<>(); // 移除不必要的synchronized,ThreadLocal本身线程安全 public static void setDriver(String browser) { WebDriver webDriver; switch (browser) { case "chrome": WebDriverManager.chromedriver().setup(); webDriver = new ChromeDriver(BrowserOptions.getChromeOptions()); break; case "fireFox": WebDriverManager.firefoxdriver().setup(); webDriver = new FirefoxDriver(BrowserOptions.getFirefoxOptions()); break; default: throw new IllegalStateException("Unexpected value: " + browser); } driver.set(webDriver); // 所有浏览器统一执行配置初始化 prepareBrowser(); } private static void prepareBrowser() { WebDriver currentDriver = getDriver(); currentDriver.manage().window().maximize(); currentDriver.manage().deleteAllCookies(); currentDriver.manage().timeouts().pageLoadTimeout(15, TimeUnit.SECONDS); currentDriver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS); } // 移除不必要的synchronized public static WebDriver getDriver() { return driver.get(); } public static void closeBrowser() { WebDriver currentDriver = getDriver(); if (currentDriver != null) { currentDriver.quit(); } // 清除当前线程的ThreadLocal副本,避免泄漏和脏数据 driver.remove(); } }
2. 类继承结构修复
删除BasePage对WorldHelper的继承,避免重复初始化逻辑:
public class BasePage { protected final WebDriver webDriver; public BasePage(WebDriver driver) { this.webDriver = driver; } }
3. WorldHelper修改
移除提前缓存的WebDriver,每次调用时从工厂取最新实例,避免拿到空值:
public class WorldHelper { private BasePage basePage; private SamplePage samplePage; public WebDriver getWebDriver() { return WebDriverFactory.getDriver(); } public SamplePage getSamplePage() { if(samplePage != null) return samplePage; samplePage = PageFactory.initElements(getWebDriver(), SamplePage.class); return samplePage; } }
修改完成后并行执行测试,所有浏览器都会正常接收执行指令,不会再出现首个浏览器空白的问题。
内容的提问来源于stack exchange,提问作者Oasis001
相关产品推荐
相关产品推荐

