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

Playwright+Java+TestNG框架执行测试时出现连接关闭错误

问题分析与解决方案

核心问题

DriverFactory类的getPage方法使用try-with-resources语法创建Playwright实例,该语法会在try代码块执行完毕后自动调用Playwright.close(),导致返回的Page对象关联的Playwright连接被提前关闭,后续调用page.navigate()时就会抛出Playwright connection closed异常。

修复步骤

1. 调整Playwright实例的生命周期

将Playwright实例提升为类成员变量,避免被自动关闭,在测试结束时手动销毁资源。修改DriverFactory类:

public class DriverFactory {
    public static ThreadLocal<Page> currentPage = new ThreadLocal<>();
    public Page page = null;
    private PropertyReader propertyReader = new PropertyReader();
    Environment environment;
    // 把Playwright设为类成员,手动控制生命周期
    private Playwright playwright;

    public DriverFactory() {
        environment = propertyReader.getEnvironment();
    }

    public Page getCurrentPage() {
        page = currentPage.get();
        return page != null ? page : null;
    }

    public void initializeBrowser(){
        currentPage.set(getPage(environment.getPlatform()));
    }

    public Page getPage(String browserName) {
        // 移除try-with-resources,手动创建Playwright
        playwright = Playwright.create();
        Browser browser = null;
        if (browserName.equalsIgnoreCase("Chrome")) {
            browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
            page = browser.newPage();
        } else if (browserName.equalsIgnoreCase("Firefox")) {
            browser = playwright.firefox().launch();
            page = browser.newPage();
        } else if (browserName.equalsIgnoreCase("edge")) {
            browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setChannel("msedge"));
            page = browser.newPage();
        } else if (browserName.equalsIgnoreCase("safari")) {
            browser = playwright.webkit().launch();
            page = browser.newPage();
        }
        System.out.println("Page ID " + page);
        return page;
    }

    // 添加销毁方法,在测试结束时关闭资源
    public void destroy() {
        Page page = currentPage.get();
        if (page != null) {
            page.close();
            currentPage.remove();
        }
        if (playwright != null) {
            playwright.close();
        }
    }
}

2. 确保WrapperMethods复用同一个DriverFactory实例

当前WrapperMethods构造方法每次新建DriverFactory,易导致线程隔离问题,改为从BaseTest传入已初始化的实例:

public class WrapperMethods {
    private DriverFactory driverFactory;
    private Page page;

    // 修改构造方法,接收外部的DriverFactory实例
    public WrapperMethods(DriverFactory driverFactory) {
        this.driverFactory = driverFactory;
    }

    public void openApplication(String url) throws InterruptedException {
        page = driverFactory.getCurrentPage();
        System.out.println(page.toString());
        page.navigate(url);
        // 建议用Playwright内置等待替代Thread.sleep,提升稳定性
        page.waitForLoadState();
    }
}

3. 在BaseTest中完成初始化与销毁逻辑

结合TestNG的注解,在测试前后执行浏览器初始化和资源销毁:

public class BaseTest {
    protected DriverFactory driverFactory;
    protected WrapperMethods wrapper;

    @BeforeMethod
    public void setup() {
        driverFactory = new DriverFactory();
        driverFactory.initializeBrowser();
        wrapper = new WrapperMethods(driverFactory);
    }

    @AfterMethod
    public void teardown() {
        driverFactory.destroy();
    }
}

4. 调整测试类

测试类直接复用BaseTest中初始化的WrapperMethods实例:

public class DesktopTest extends BaseTest {
    @Test
    public void navigateToWebPage() throws InterruptedException {
        wrapper.openApplication("https://www.youtube.com");
    }
}

额外建议

  • 彻底移除Thread.sleep(),改用Playwright提供的等待API(如page.waitForLoadState()、page.waitForSelector()),避免因等待时间不合理导致的不稳定问题。
  • 将浏览器启动参数(如是否无头、浏览器通道)配置到properties文件中,实现配置与代码解耦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:36:15