并行执行TestNG测试时如何向监听器传递各测试用例独有的参数
问题根源
ITestContext是TestNG中<test>标签对应范围内所有测试方法共享的全局上下文,你开启了测试方法并行执行,多个线程同时修改同一个context的属性,后写入的值会直接覆盖之前的值,最终所有用例读取到的都是最后一次设置的属性值。- 代码存在属性名大小写不一致问题:写入时用的属性名是
testCaseNo,读取时用的是testcaseNo,也会导致属性读取异常。 - 将
WebDriver实例存在共享context中会导致资源泄漏:并行执行时每个用例都会创建一个driver,但context中只会保留最后创建的driver实例,最终仅最后一个driver会被关闭,其余driver进程会残留在系统中。
修复方案
核心逻辑是将单测试用例独有的参数存储到每个用例专属的ITestResult实例中,ITestResult是每个测试用例执行时独有的对象,不会被其他用例覆盖,修改后的代码如下:
Java代码修改
public class Myproject implements ITestListener{ @Test(dataProvider = "getData") // 替换注入的ITestContext为ITestResult public static void test1(int i,ITestResult result){ System.setProperty("webdriver.chrome.driver", ".\\drivers\\chromedriver.exe"); WebDriver driver=new ChromeDriver(); driver.get(url); // 将用例专属属性存入当前用例的ITestResult中 result.setAttribute("driver", driver); result.setAttribute("testCaseNo",i+1); equalToOne(i); } @DataProvider(parallel = true) public Object[][] getData() { Object[][] data = new Object[4][1]; data[0][0] = 0; data[1][0] = 1; data[2][0] = 2; data[3][0] = 3; return data; } public static void equalToOne(int k){ Assert.assertEquals(1,k); } @Override public void onTestStart(ITestResult result) { } @Override public void onTestSuccess(ITestResult result) { // 直接从当前用例的ITestResult读取属性 int i=(int) result.getAttribute("testCaseNo"); System.out.println("Testcase " + i + " Passed"); // 用完直接关闭当前用例的driver WebDriver driver = (WebDriver) result.getAttribute("driver"); if(driver != null) driver.quit(); } @Override public void onTestFailure(ITestResult result) { int i=(int) result.getAttribute("testCaseNo"); System.out.println("Testcase " + i + " Failed"); WebDriver driver = (WebDriver) result.getAttribute("driver"); if(driver != null) driver.quit(); } @Override public void onTestSkipped(ITestResult result) { // 跳过的用例也要关闭driver WebDriver driver = (WebDriver) result.getAttribute("driver"); if(driver != null) driver.quit(); } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { } @Override public void onStart(ITestContext context) { } @Override public void onFinish(ITestContext context) { // 移除原有的driver关闭逻辑,每个用例执行完自行关闭 } }
XML配置无需修改
原有XML配置已经开启了方法级并行和对应监听器,无需调整。
修改后即可得到你预期的输出结果,不会出现属性覆盖的问题。
内容的提问来源于stack exchange,提问作者Arun Kumar S
相关产品推荐
相关产品推荐

