TestNG并行执行测试时如何复用WebDriver驱动实例
TestNG并行测试复用浏览器驱动实现方案
核心逻辑是将驱动生命周期从测试方法级调整为工作线程级,通过ThreadLocal做线程隔离的驱动存储,驱动实例数和配置的thread-count数值完全一致,所有用例复用空闲线程绑定的已有驱动,无需反复启停。
第一步:实现线程绑定的驱动管理类
新建统一的驱动管理类,通过ThreadLocal为每个工作线程存储独立的驱动实例,线程首次获取驱动时才执行初始化,后续调用直接返回已有实例:
import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import java.time.Duration; public class DriverManager { // 线程隔离存储驱动,每个工作线程对应一个独立驱动实例 private static final ThreadLocal<WebDriver> DRIVER_THREAD_LOCAL = new ThreadLocal<>(); // 替换为你实际的全局配置,和原有代码的配置对象保持一致即可 private static String url = "你的测试系统地址"; private static Properties prop; private static Date date; public static WebDriver getDriver() { // 当前线程未绑定驱动时才执行初始化,每个线程仅执行一次 if (DRIVER_THREAD_LOCAL.get() == null) { // 替换为你实际的驱动创建逻辑,比如根据浏览器参数初始化Chrome/Firefox驱动 WebDriver driver = new ChromeDriver(); // 驱动基础配置 driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get(url); // 原有前置业务逻辑(登录、跳过改密提示)放在这里,每个驱动仅执行一次 Demo_Page objDemoPage = new Demo_Page(driver, prop, date); objDemoPage.admin_demo("local"); Home_page objHomePage = new Home_page(driver, prop, date); objHomePage.pwd_change_later(); // 将初始化完成的驱动绑定到当前线程 DRIVER_THREAD_LOCAL.set(driver); } return DRIVER_THREAD_LOCAL.get(); } // 销毁当前线程绑定的驱动,供测试全部完成后调用 public static void cleanDriver() { if (DRIVER_THREAD_LOCAL.get() != null) { DRIVER_THREAD_LOCAL.get().quit(); DRIVER_THREAD_LOCAL.remove(); } } }
第二步:调整测试类注解逻辑
- 删除原有
@BeforeMethod中所有驱动初始化、前置登录相关代码,这部分逻辑已经移到驱动管理类的初始化流程中 - 删除原有
@AfterMethod中getDriver().quit()的驱动关闭逻辑,避免单个用例执行完销毁驱动 - 测试类中所有获取驱动的逻辑,统一替换为调用
DriverManager.getDriver(),不需要在单个测试类中单独维护ThreadLocal驱动存储
第三步:新增Suite级监听器处理最终驱动销毁
新建TestNG套件监听器,在全量用例执行完成后统一销毁所有线程绑定的驱动:
import org.testng.ISuite; import org.testng.ISuiteListener; public class SuiteDriverListener implements ISuiteListener { @Override public void onFinish(ISuite suite) { // 整个测试套件所有用例执行完成后,关闭当前线程绑定的驱动 DriverManager.cleanDriver(); } }
第四步:调整testng.xml配置
- 将并行模式从
parallel="tests"修改为parallel="methods",保证TestNG用固定大小的线程池(大小为thread-count配置值)调度所有测试方法 - 将新增的套件监听器加入监听器列表
配置示例如下:
<suite name="Suite" parallel="methods" thread-count="2"> <listeners> <listener class-name="listeners3.Proj_Listener" /> <listener class-name="你的实际类路径.SuiteDriverListener" /> </listeners> <!-- 原有<test>标签内容保持不变即可 --> </suite>
注意事项
- 可以保留
@AfterMethod注解,但方法内仅能写用例状态重置逻辑,比如跳转回系统首页、清理当前用例生成的测试数据,避免上一个用例的操作上下文影响同线程下执行的下一个用例,示例代码:
@AfterMethod public void resetTestStatus() { // 示例:用例执行完回到首页,保证下一个用例起始状态统一 DriverManager.getDriver().get("你的系统首页地址"); }
- 所有测试代码中禁止手动调用
driver.quit(),驱动销毁逻辑统一交给套件监听器处理 - 这套逻辑下启动的浏览器实例数和
thread-count配置值完全一致,比如配置thread-count="2"就只会启动2个浏览器,所有用例排队复用这2个实例执行,不会出现每个用例启停浏览器的问题
内容的提问来源于stack exchange,提问作者Nandy
相关产品推荐
相关产品推荐

