You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:05:49