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

Playwright+C#并行测试报错:InvalidOperationException与TargetClosedException

问题分析与解决方案

核心问题根源

你的测试并行执行失败主要由两个原因导致:

  1. 异步代码错误使用:直接调用.Result阻塞异步方法,破坏异步执行上下文,在并行场景下引发资源竞争和时序混乱。
  2. 资源生命周期管理不当:页面/上下文的创建、销毁逻辑存在竞态条件,加上可能的非线程安全集合操作,导致TearDown阶段枚举集合时出错,以及截图时目标已关闭。

具体修复步骤

1. 修复异步代码的阻塞问题

你的代码中使用.Result直接获取异步操作结果,会导致线程阻塞,在并行测试时极易引发异步操作未完成就继续执行后续代码的问题。将所有异步调用改为await:

[Test]
[AllureStep]
public async Task UserNameEditable()
{
    // 改用await创建上下文和页面,避免阻塞线程
    var context = await Browser.NewContextAsync(new CustomBrowserNewContextOptions().Create());
    var page = await context.NewPageAsync();
    try
    {
        LoginPage loginPage = new LoginPage(page);
        await loginPage.VisitPage(_baseUrl);
        var userNameField = loginPage.GetUserNameLocator();
        await Assertions.Expect(userNameField).ToBeEditableAsync();
        await AllureScreenshot.TakeAllureScreenshot(
            page,
            "Username field is editable",
            Status.passed
        );
    }
    catch (Exception ex)
    {
        await AllureScreenshot.TakeAllureScreenshot(
            page,
            "Username editable test failed",
            Status.failed
        );
        Assert.Fail($"Username field on login page is not editable : {ex.Message}");
    }
    finally
    {
        // 用finally确保无论成功失败都关闭页面和上下文,避免资源泄漏
        await page.CloseAsync();
        await context.CloseAsync();
    }
}

2. 确保资源的线程安全与生命周期

  • 每个测试用例应独立创建**浏览器上下文(Context)**和页面,完全隔离测试资源;
  • 使用finally块统一处理资源关闭,避免异常场景下资源未释放;
  • 如果BaseTestSetup中维护了测试资源集合(如跟踪创建的上下文),必须用线程安全集合(如ConcurrentBag<T>)代替普通List<T>,防止并行修改时引发枚举异常。

3. 修复TearDown阶段的非线程安全问题

第一个异常出现在BrowserTest.BrowserTearDown()的集合枚举中,说明Playwright.NUnit内部的资源跟踪集合被并行测试修改:

  • 检查BaseTestSetup是否重写了TearDown逻辑,若有则确保所有集合操作线程安全;
  • 若继承自BrowserTest,不要自定义可能干扰资源跟踪的逻辑,让Playwright自行管理资源生命周期。

4. 验证Playwright并行配置

[Parallelizable(ParallelScope.All)]的设置没问题,但要确保:

  • 测试类级别仅共享Browser实例(Playwright的IBrowser本身是线程安全的);
  • 所有测试方法的上下文、页面等资源完全独立,不跨测试共享。

额外注意事项

  • 若JsonDataManager.Instance是单例,需确保其内部操作线程安全,避免并行测试时的状态冲突;
  • 截图操作必须在页面关闭前完成,finally块的关闭逻辑能保证这一点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 23:40:53