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

如何通过TestNG XML实现LeanFT测试在Chrome中独立多线程并行执行?

解决LeanFT+TestNG并行测试时Chrome共用窗口的Cookie冲突问题

我之前做LeanFT并行测试时也碰到过一模一样的问题——明明TestNG配置了并行,结果所有测试都挤在同一个Chrome窗口里,登录登出的Cookie互相干扰,简直头疼。咱们一步步来解决这个问题:

问题根源

LeanFT默认会尝试复用已有的Chrome浏览器实例,尤其是当你没有指定独立的用户数据目录时,所有线程都会共享同一个浏览器的缓存和Cookie池,自然就会出现冲突。再加上你代码里的browser.clearCache(),更是会把其他线程的缓存也清掉,问题就更严重了。

解决方案:让每个线程拥有独立的Chrome实例

核心思路是给每个线程的Chrome实例分配一个唯一的用户数据目录,同时用线程本地存储(ThreadLocal)确保每个线程拿到自己的浏览器实例,不共享。

1. 使用ThreadLocal存储浏览器实例

ThreadLocal可以保证每个线程拥有自己独立的变量副本,避免多线程之间的实例共享。我们先定义一个ThreadLocal来存Browser:

import com.hp.lft.sdk.web.Browser;
import com.hp.lft.sdk.web.BrowserFactory;
import com.hp.lft.sdk.web.BrowserType;
import com.hp.lft.sdk.web.BrowserLaunchOptions;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.testng.annotations.AfterMethod;

public class BaseTest {
    // 每个线程独立的Browser实例
    private static ThreadLocal<Browser> threadLocalBrowser = new ThreadLocal<>();
    // 每个线程的临时用户数据目录,用于后续清理
    private static ThreadLocal<File> threadLocalTempDir = new ThreadLocal<>();

    public Browser getBrowser() {
        if (threadLocalBrowser.get() == null) {
            try {
                // 创建一个唯一的临时目录,作为当前线程Chrome的用户数据目录
                File tempDir = Files.createTempDirectory("leanft_chrome_thread_").toFile();
                threadLocalTempDir.set(tempDir);

                // 配置Chrome启动选项,指定独立的用户数据目录
                BrowserLaunchOptions launchOptions = new BrowserLaunchOptions();
                launchOptions.setUserDataDir(tempDir.getAbsolutePath());
                launchOptions.setCleanSession(true); // 确保每个会话都是全新的

                // 启动独立的Chrome实例
                Browser browser = BrowserFactory.launch(BrowserType.CHROME, launchOptions);
                threadLocalBrowser.set(browser);
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("Failed to create temp directory for Chrome user data", e);
            }
        }
        return threadLocalBrowser.get();
    }

    // 测试结束后清理资源
    @AfterMethod
    public void teardown() {
        // 关闭当前线程的浏览器
        Browser browser = threadLocalBrowser.get();
        if (browser != null && browser.isOpen()) {
            browser.close();
            threadLocalBrowser.remove();
        }

        // 删除临时用户数据目录,避免磁盘占用
        File tempDir = threadLocalTempDir.get();
        if (tempDir != null && tempDir.exists()) {
            deleteDirectory(tempDir);
            threadLocalTempDir.remove();
        }
    }

    // 递归删除目录(如果不想引入Apache Commons IO,可以自己实现)
    private void deleteDirectory(File dir) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                deleteDirectory(file);
            }
        }
        dir.delete();
    }
}

2. 确保TestNG配置正确

你的TestNG XML配置parallel="tests" thread-count="2"是没问题的,但需要注意:

  • 测试类不要使用静态变量存储浏览器实例,所有与浏览器相关的操作都通过getBrowser()获取当前线程的实例
  • 如果是parallel="methods",上面的ThreadLocal方案也能覆盖这种情况,每个测试方法都会拿到自己的浏览器实例

3. 为什么这样能解决问题?

  • 独立用户数据目录:每个Chrome实例都有自己的缓存、Cookie和会话存储,完全隔离,不会互相干扰
  • ThreadLocal隔离实例:保证每个线程只能拿到自己的Browser对象,不会出现多个线程操作同一个浏览器窗口的情况
  • 自动清理资源:测试结束后关闭浏览器并删除临时目录,避免残留文件占用磁盘空间

额外注意事项

  • 如果你使用的LeanFT版本比较旧,需要确认BrowserLaunchOptions是否支持setUserDataDir方法(新版本都支持)
  • 临时目录的创建需要有足够的磁盘权限,否则会抛出IO异常
  • 如果测试执行后临时目录没有被删除,可以手动检查是否有文件被占用,或者调整删除逻辑

内容的提问来源于stack exchange,提问作者sreeram kartheek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:51:34