TestNG方法并行执行仅运行最后调用方法的问题排查
问题排查与解决方案
嘿,我一眼就看出你遇到的核心问题了——TestNG并行执行时的线程安全冲突!你的代码里BaseClass的driver是公共实例变量,当多个线程并行运行测试方法时,它们会共享这个变量,导致后面的线程覆盖前面线程的driver引用,这就是为什么前两个浏览器没执行操作,第三个浏览器却出现了parallelmethodtestng这种拼接输入的原因(三个测试方法的sendKeys都发到了同一个driver实例上)。
问题根源拆解
当你设置parallel="methods"时,TestNG默认会为同一个测试类的所有方法复用同一个实例。这意味着三个测试方法会共享BaseClass里的public WebDriver driver变量:
- 线程1启动,创建driverA,赋值给
driver变量 - 线程2启动,创建driverB,覆盖
driver变量为driverB - 线程3启动,创建driverC,覆盖
driver变量为driverC - 最终三个测试方法都使用driverC执行,导致前两个浏览器(driverA、driverB)完全没被操作,而driverC接收了所有三次输入。
修复方案:用ThreadLocal实现线程隔离
我们需要为每个线程维护独立的WebDriver实例,ThreadLocal正好能帮我们做到这一点——它会为每个线程存储专属的变量副本,互不干扰。
修改后的BaseClass
import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import java.util.concurrent.TimeUnit; public class BaseClass { // 用ThreadLocal存储每个线程独有的WebDriver和WebDriverWait private ThreadLocal<WebDriver> driverThreadLocal = new ThreadLocal<>(); private ThreadLocal<WebDriverWait> waitThreadLocal = new ThreadLocal<>(); @BeforeMethod() public void configure() { System.setProperty("webdriver.chrome.driver","C:\\SeleniumDrivers\\chromedriver.exe"); WebDriver driver = new ChromeDriver(); driver.get("https://www.google.com"); driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); // 将当前线程的driver存入ThreadLocal driverThreadLocal.set(driver); waitThreadLocal.set(new WebDriverWait(driver, 10)); } @AfterMethod() public void tearDown() { WebDriver driver = driverThreadLocal.get(); if (driver != null) { driver.quit(); // 移除ThreadLocal中的实例,避免内存泄漏 driverThreadLocal.remove(); waitThreadLocal.remove(); } } // 提供获取driver的公共方法,供测试类调用 public WebDriver getDriver() { return driverThreadLocal.get(); } public WebDriverWait getWait() { return waitThreadLocal.get(); } }
修改后的测试类NewTest
把原来直接访问driver的地方,换成调用getDriver()方法:
import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.testng.annotations.Test; public class NewTest extends BaseClass{ @Test() public void method1() { getDriver().findElement(By.name("q")).sendKeys("parallel"); getDriver().findElement(By.name("q")).sendKeys(Keys.ENTER); } @Test() public void method2() { getDriver().findElement(By.name("q")).sendKeys("methods"); getDriver().findElement(By.name("q")).sendKeys(Keys.ENTER); } @Test() public void method3() { getDriver().findElement(By.name("q")).sendKeys("testng"); getDriver().findElement(By.name("q")).sendKeys(Keys.ENTER); } }
可选优化:调整suite的thread-count
你的suite里thread-count="5"可以改成3,因为你只有3个测试方法,开3个线程刚好匹配,避免资源浪费:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Suite" parallel="methods"> <test thread-count="3" name="Test"> <classes> <class name="website.NewTest"/> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
验证效果
修改后运行suite,你会看到三个浏览器并行打开,分别执行各自的搜索操作,执行完成后自动关闭,测试结果也会显示Total tests run: 3, Failures: 0。
内容的提问来源于stack exchange,提问作者Hari
相关产品推荐
相关产品推荐

