基于TestNG与Selenium Driver Factory的并行执行问题求助
我来帮你梳理下可能导致并行执行未生效的关键点,结合你的配置和代码给出具体调整方案:
1. 修正Surefire插件的配置错误
你当前把suiteXmlFiles放在了<properties>标签下,这是不正确的——Surefire插件的suiteXmlFiles配置应该直接放在<configuration>根节点下,否则插件无法正确读取TestNG的suite配置,自然不会启用并行执行。
修改后的Surefire配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> <configuration> <!-- 直接将suiteXmlFiles放在configuration下,而非properties内 --> <suiteXmlFiles> <suiteXmlFile>src/main/resources/master.xml</suiteXmlFile> </suiteXmlFiles> </configuration> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> </dependencies> </plugin>
2. 升级TestNG版本到稳定版
你使用的TestNG 6.9.10是比较老旧的版本,存在一些并行执行相关的已知bug(比如线程隔离失效、ThreadLocal资源泄漏等)。建议升级到TestNG 7.x的稳定版本,比如7.6.1:
<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.6.1</version> <scope>test</scope> </dependency>
同时,建议把Surefire插件也升级到匹配的版本(比如3.1.2),确保插件和TestNG版本兼容:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.1.2</version> <!-- 其余配置保持不变 --> </plugin>
3. 优化DriverFactory的线程安全实现
你的DriverFactory已经用了ThreadLocal,但有几个细节可以优化,确保每个线程的WebDriver实例完全隔离:
- 把
ThreadLocal<WebDriver>声明为private static,避免实例化多个DriverFactory时出现线程泄漏; - 优化初始化逻辑,添加双重检查锁避免重复创建实例,同时增加异常处理;
修改后的DriverFactory:
public class DriverFactory { private DriverFactory() {} private static final DriverFactory instance = new DriverFactory(); private static final ThreadLocal<WebDriver> driverThreadLocal = new ThreadLocal<>(); public static DriverFactory getInstance() { return instance; } public WebDriver getDriver() { if (driverThreadLocal.get() == null) { synchronized (DriverFactory.class) { if (driverThreadLocal.get() == null) { System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe"); driverThreadLocal.set(new ChromeDriver()); } } } return driverThreadLocal.get(); } public void removeDriver() { WebDriver driver = driverThreadLocal.get(); if (driver != null) { driver.quit(); driverThreadLocal.remove(); } } }
4. 确保测试类正确管理WebDriver生命周期
在你的测试类中,需要在每个测试方法结束后(或者每个测试类结束后)调用removeDriver(),释放当前线程的WebDriver资源,避免影响后续线程的执行。比如使用TestNG的@AfterMethod或@AfterClass注解:
示例测试类:
public class TestCase1 { private WebDriver driver; @BeforeMethod public void setUp() { driver = DriverFactory.getInstance().getDriver(); driver.get("https://example.com"); } @Test public void testCase1() { // 测试逻辑 System.out.println("TestCase1 running on thread: " + Thread.currentThread().getId()); } @AfterMethod public void tearDown() { DriverFactory.getInstance().removeDriver(); } }
验证并行执行的方法
执行mvn clean test后,可以通过控制台日志查看线程ID,如果两个测试类的线程ID不同,说明并行执行生效了。比如日志中会出现类似:
TestCase1 running on thread: 12 TestCase2 running on thread: 13
按照以上步骤调整后,应该能解决TestNG类并行执行的问题。如果还是有问题,可以检查ChromeDriver的版本是否和Chrome浏览器版本匹配,或者尝试在master.xml中添加verbose="2"来查看更详细的TestNG执行日志,定位具体问题。
内容的提问来源于stack exchange,提问作者petermartin2002

