首页
/ Playwright C 入门实战:从 dotnet new 到跑通首个端到端测试

Playwright C 入门实战:从 dotnet new 到跑通首个端到端测试

2026-09-06 13:04:42作者:瞿蔚英Wynne

本篇指南基于 Playwright 仓库中的官方 C# 安装文档 intro-csharp.md 展开,带你完整走通「创建 .NET 测试项目 → 安装 Playwright 依赖 → 下载浏览器 → 编写并运行首个端到端测试」的全流程,并深入解析 MSTest、NUnit、xUnit、xUnit v3 四套测试框架基类的差异、PageTest 生命周期设计,以及 BROWSERHEADEDPWDEBUG 等关键运行参数的底层行为。读完你将在 Windows、Linux 或 macOS 上具备独立搭建 Playwright C# 测试工程并按需切换浏览器引擎与运行模式的能力。

一、Playwright 的定位与 C# 集成方式

Playwright 是专为端到端(E2E)测试设计的框架,支持 Chromium、WebKit、Firefox 三大现代渲染引擎,可在 Windows、Linux、macOS 上本地或 CI 中运行,支持 headless/headed 模式与原生移动端模拟。

在 .NET 生态中,Playwright 提供两条使用路径(详见 intro-csharp.md):

路径 说明 适用场景
测试框架基类 通过 Microsoft.Playwright.MSTest / Microsoft.Playwright.NUnit / Microsoft.Playwright.Xunit / Microsoft.Playwright.Xunit.v3 包提供 PageTestContextTest 等基类,开箱即得「每个测试独立的 Page / BrowserContext」、跨引擎运行、测试并行化、launch/context 选项调整 标准 E2E 测试工程(推荐入门路径)
Playwright 库 直接使用 Microsoft.Playwright 包手动管理 PlaywrightBrowserBrowserContext 生命周期 自研测试基建或与其他测试框架集成,详见 library-csharp.md

二、系统要求

根据 intro-csharp.md 的官方要求,当前版本的运行环境前提为:

  • Playwright 以 .NET Standard 2.0 库形式分发,官方推荐 .NET 8
  • Windows 11+、Windows Server 2019+ 或 WSL
  • macOS 14 (Sonoma) 或更高版本
  • Debian 12 / 13、Ubuntu 22.04 / 24.04 / 26.04(x86-64 或 arm64)。

三、安装流程四步走

第 1 步:用 dotnet new 创建测试项目

四种测试框架各自对应一个 dotnet new 模板,执行后会生成 PlaywrightTests 目录,其中包含示例测试文件 UnitTest1.cs

测试框架 创建命令
MSTest dotnet new mstest -n PlaywrightTests
NUnit dotnet new nunit -n PlaywrightTests
xUnit (v2) dotnet new xunit -n PlaywrightTests
xUnit v3 dotnet new xunit3 -n PlaywrightTests
# 以 MSTest 为例
dotnet new mstest -n PlaywrightTests
cd PlaywrightTests

注意 xUnit v3 的模板名是 xunit3(不是 xunit),模板命名差异是常见踩坑点。

第 2 步:安装对应的 Playwright NuGet 包

测试框架 NuGet 包
MSTest dotnet add package Microsoft.Playwright.MSTest
NUnit dotnet add package Microsoft.Playwright.NUnit
xUnit (v2) dotnet add package Microsoft.Playwright.Xunit
xUnit v3 dotnet add package Microsoft.Playwright.Xunit.v3

每个包对应一个独立命名空间(Microsoft.Playwright.MSTestMicrosoft.Playwright.NUnitMicrosoft.Playwright.XunitMicrosoft.Playwright.Xunit.v3),基类位于同名命名空间内,详见 test-runners-csharp.md

第 3 步:构建项目,产出 playwright.ps1

dotnet build

构建完成后,bin 目录(如 bin/Debug/net8.0/)下会出现 playwright.ps1 脚本。这个脚本的作用等价于 JS 生态的 npx playwright install——它驱动 Playwright 自带的 driver 下载对应平台的浏览器二进制。从源码可以印证这一机制:registry/index.ts 中,当检测到 .NET 环境时会提示用户执行 pwsh bin/Debug/netX/playwright.ps1 <parameters>,即该脚本是浏览器注册表(registry)安装流程的 .NET 入口。

第 4 步:安装浏览器

pwsh bin/Debug/net8.0/playwright.ps1 install
  • 示例使用 net8.0,如果你的 .NET 版本不同,需将路径中的 net8.0 替换为实际输出目录名(如 net9.0);
  • 如果系统没有 pwsh,需要先安装 PowerShell 才能执行该脚本。

四、编写示例端到端测试

编辑项目中的 UnitTest1.cs。以最典型的 MSTest 版本为例,核心要点是:继承 PageTest 基类,直接使用注入的 Page 属性,无需手动启动浏览器或创建上下文:

using System.Text.RegularExpressions;
using Microsoft.Playwright;
using Microsoft.Playwright.MSTest;

namespace PlaywrightTests;

[TestClass]
public class ExampleTest : PageTest
{
    [TestMethod]
    public async Task HasTitle()
    {
        await Page.GotoAsync("https://playwright.dev");

        // Expect a title "to contain" a substring.
        await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
    }

    [TestMethod]
    public async Task GetStartedLink()
    {
        await Page.GotoAsync("https://playwright.dev");

        // Click the get started link.
        await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();

        // Expects page to have a heading with the name of Installation.
        await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
    }
}

其余三种框架的写法差异仅在于 using 命名空间、特性标注和基类来源,示例(摘自 intro-csharp.md):

  • NUnitusing Microsoft.Playwright.NUnit;,类上标注 [Parallelizable(ParallelScope.Self)][TestFixture],测试方法用 [Test]
  • xUnit v2using Microsoft.Playwright.Xunit;,测试方法用 [Fact],类无需额外特性;
  • xUnit v3using Microsoft.Playwright.Xunit.v3;,写法与 xUnit v2 一致。

基类家族:PageTest / ContextTest / BrowserTest / PlaywrightTest

官方测试运行器文档 定义了四个可用的基类,理解它们的生命周期是正确使用 C# 版 Playwright 的关键:

基类 每个测试获得的资源 说明
PageTest 一个独立 BrowserContext 中新建的 Page 最简路径,写单页 E2E 测试首选;可重写 ContextOptions() 方法控制上下文选项(即传给 browser.newContext() 的参数),按文件粒度设置各类模拟选项
ContextTest 一个新的 BrowserContext 适合多标签页场景,可自建任意多个 Page;同样支持重写 ContextOptions()
BrowserTest 一个 Browser 实例 可自建多个 Context,但每个测试需自行负责清理所创建的上下文
PlaywrightTest 一个 Playwright 对象 最底层,测试可自行启动/停止任意多个浏览器

性能与隔离策略上,官方明确说明:PlaywrightBrowser 实例会在测试之间复用(提升性能),而推荐每个测试使用全新的 BrowserContext,以实现浏览器状态隔离。

五、运行测试与常用参数

基础运行

dotnet test

默认行为(来自 intro-csharp.md「Running the Example Tests」):

  • 默认在 Chromium 上运行
  • 默认 headless 模式——不会弹出浏览器窗口,结果与日志输出到终端;
  • 可通过 BROWSER 环境变量切换引擎,或调整 launch 配置项。

切换浏览器引擎

方式一:BROWSER 环境变量(各平台写法,摘自 running-tests-csharp.md):

# bash
BROWSER=webkit dotnet test
# batch
set BROWSER=webkit
dotnet test
# powershell
$env:BROWSER="webkit"
dotnet test

方式二:runsettings 参数直接指定:

dotnet test -- Playwright.BrowserName=webkit

需要在多个浏览器/配置上批量回归时,分别执行多次 dotnet test 并配合各自的 runsettings 文件:

dotnet test --settings:chromium.runsettings
dotnet test --settings:firefox.runsettings
dotnet test --settings:webkit.runsettings

对应的 runsettings 示例:

<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <Playwright>
    <BrowserName>chromium</BrowserName>
  </Playwright>
</RunSettings>

有头模式(headed)

HEADED=1 dotnet test                # bash
set HEADED=1 && dotnet test         # Windows batch
$env:HEADED="1"; dotnet test        # PowerShell

选择性运行

# 按测试类名过滤单个文件
dotnet test --filter "ExampleTest"
# 多个类
dotnet test --filter "ExampleTest1|ExampleTest2"
# 按测试方法名过滤
dotnet test --filter "Name~GetStartedLink"

并行 worker 数量

各框架的默认并行行为与调参方式(摘自 test-runners-csharp.md):

框架 默认行为 调参命令 限制
NUnit 所有测试文件并行,文件内顺序执行(ParallelScope.Self dotnet test -- NUnit.NumberOfTestWorkers=5 仅支持 ParallelScope.Self
MSTest 所有测试类并行,类内顺序执行(ExecutionScope.ClassLevel dotnet test --settings:.runsettings -- MSTest.Parallelize.Workers=4 不支持方法级并行(MethodLevel
xUnit 所有测试类并行,类内顺序执行 dotnet test -- xUnit.MaxParallelThreads=5 推荐 xUnit 2.8+,默认使用 conservative 并行算法
xUnit v3 同 xUnit dotnet test -- xUnit.MaxParallelThreads=5 默认 conservative 并行算法

官方建议:CPU 密集型测试的 worker 数取核心数的一半,IO 密集型可取全部核心数。

六、进阶配置:ContextOptions 与 Browser launch 选项

重写 ContextOptions 定制浏览器上下文

在派生自 PageTest / ContextTest 的测试类中重写 ContextOptions() 方法,即可为该文件下所有测试统一注入模拟选项:

using System.Threading.Tasks;
using Microsoft.Playwright;
using Microsoft.Playwright.MSTest;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace PlaywrightTests;

[TestClass]
public class ExampleTest : PageTest
{
    [TestMethod]
    public async Task TestWithCustomContextOptions()
    {
        // 此时 Page(及其 BrowserContext)已应用自定义的 colorScheme、viewport 与 baseURL:
        await Page.GotoAsync("/login");
    }

    public override BrowserNewContextOptions ContextOptions()
    {
        return new BrowserNewContextOptions()
        {
            ColorScheme = ColorScheme.Light,
            ViewportSize = new()
            {
                Width = 1920,
                Height = 1080
            },
            BaseURL = "https://github.com",
        };
    }
}

注意 BaseURL 生效后可直接用相对路径 GotoAsync("/login")

用 runsettings 定制 Browser / launch 选项

浏览器级选项(引擎名、headless、channel 等)通过 runsettings 文件或 CLI 参数覆盖:

<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <Playwright>
    <BrowserName>chromium</BrowserName>
    <LaunchOptions>
      <Headless>false</Headless>
      <Channel>msedge</Channel>
    </LaunchOptions>
  </Playwright>
</RunSettings>
dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Headless=false Playwright.LaunchOptions.Channel=msedge

完整的 runsettings 参考(含并行设置、ExpectTimeout、调试环境变量,摘自 test-runners-csharp.md):

<RunSettings>
  <!-- MSTest adapter -->
  <MSTest>
    <Parallelize>
      <Workers>4</Workers>
      <Scope>ClassLevel</Scope>
    </Parallelize>
  </MSTest>
  <!-- General run configuration -->
  <RunConfiguration>
    <EnvironmentVariables>
      <!-- For debugging selectors, it's recommended to set the following environment variable -->
      <DEBUG>pw:api</DEBUG>
    </EnvironmentVariables>
  </RunConfiguration>
  <!-- Playwright -->
  <Playwright>
    <BrowserName>chromium</BrowserName>
    <ExpectTimeout>5000</ExpectTimeout>
    <LaunchOptions>
      <Headless>false</Headless>
      <Channel>msedge</Channel>
    </LaunchOptions>
  </Playwright>
</RunSettings>

NUnit / xUnit / xUnit v3 版本仅 adapter 节点不同:<NUnit><NumberOfTestWorkers>24</NumberOfTestWorkers></NUnit><xUnit><MaxParallelThreads>1</MaxParallelThreads></xUnit>Playwright 节点与上相同。

七、调试 Playwright C# 测试

Playwright 运行在 .NET 进程中,可直接用 Visual Studio 或 VS Code 调试器断点调试。此外 Playwright 自带 Playwright Inspector

PWDEBUG=1 dotnet test

开启后可逐步单步执行 Playwright API 调用、查看调试日志并探索 locator 状态。

若开启了 verbose API 日志(通过 DEBUG=pw:api 环境变量),消息会输出到标准错误流;在 Visual Studio 中对应 Output 窗口的 Tests 窗格,同时也会出现在每个测试的 Test Log 中。从仓库源码看,PWDEBUG 相关的调试钩子实现在浏览器上下文层面,可参考 browserContext.ts 与 CLI 入口 program.ts,它们对 C# 与 JS 生态是共享的同一套 driver。

八、替代路径:直接使用 Microsoft.Playwright 库

如果不使用测试框架基类,可以按 library-csharp.md 手动搭建:

dotnet new console -n PlaywrightDemo
cd PlaywrightDemo
dotnet add package Microsoft.Playwright
dotnet build
# 安装浏览器(netX 替换为实际输出目录名,如 net8.0)
pwsh bin/Debug/netX/playwright.ps1 install

最小可运行示例:

using Microsoft.Playwright;

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.GotoAsync("https://playwright.dev/dotnet");
await page.ScreenshotAsync(new()
{
    Path = "screenshot.png"
});

库模式下同样可用 web-first 断言(自动重试直到条件满足或超时):

using Microsoft.Playwright;
using static Microsoft.Playwright.Assertions;

// 按需修改默认 5 秒超时
SetDefaultExpectTimeout(10_000);

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.GotoAsync("https://playwright.dev/dotnet");
await Expect(page.GetByRole(AriaRole.Link, new() { Name = "Get started" })).ToBeVisibleAsync();

跨平台发布时,Playwright 默认只打包发布目标运行时对应的 driver,可在项目文件中通过 PlaywrightPlatform 覆盖(取值 allnonelinuxwinosx,可用 ; 组合):

<PropertyGroup>
  <PlaywrightPlatform>all</PlaywrightPlatform>
</PropertyGroup>

九、仓库内延伸阅读

主题 路径
C# 安装指南(本文主体文档) docs/src/intro-csharp.md
测试框架基类与并行策略 docs/src/test-runners-csharp.md
运行与调试测试 docs/src/running-tests-csharp.md
库模式使用与断言 docs/src/library-csharp.md
Web-first 断言与 locator 写法 docs/src/writing-tests-csharp.md
Codegen 生成测试 docs/src/codegen-intro.md
Trace Viewer 查看测试轨迹 docs/src/trace-viewer-intro-csharp.md
CI 上运行 C# 测试 docs/src/ci-intro.md
文档校验与 API 文档工具链 utils/doclint/

以上链接中的文档由仓库自带的文档工具链统一校验(见 package.json 中的 doc 脚本),保证示例命令与 API 描述和实现保持一致。

登录后查看全文
热门项目推荐
相关项目推荐