# 端到端测试 本文档旨在为 Gutenberg 项目中如何使用 Playwright 编写端到端测试提供操作指南和最佳实践。
若您正在使用旧版 Jest + Puppeteer 框架,请参阅专用指南。若需从 Jest + Puppeteer 迁移测试,请查阅迁移指南
## 运行测试 ```bash # 运行所有可用测试 npm run test:e2e # 以图形界面模式运行 npm run test:e2e -- --headed # 在特定浏览器中运行测试(支持 `chromium`、`firefox` 或 `webkit`) npm run test:e2e -- --project=webkit --project=firefox # 运行单个测试文件 npm run test:e2e -- <测试文件路径> # 例如:npm run test:e2e -- site-editor/title.spec.js # 调试模式 npm run test:e2e -- --debug ``` 若您在 Linux 环境下开发,目前需以图形界面模式测试 Webkit 浏览器。若不愿或无法使用图形界面运行(例如无图形界面环境),可在命令前添加 [`xvfb-run`](https://manpages.ubuntu.com/manpages/xenial/man1/xvfb-run.1.html) 在虚拟环境中运行: ```bash # 运行所有可用测试 xvfb-run npm run test:e2e # 仅运行 webkit 测试 xvfb-run -- npm run test:e2e -- --project=webkit ``` 若您正在使用 VS Code 进行编辑,可安装 [Playwright 扩展插件](https://playwright.dev/docs/getting-started-vscode)来辅助运行、编写和调试测试。 ## 最佳实践 请阅读 Playwright 的[最佳实践指南](https://playwright.dev/docs/best-practices)。 ### 禁止使用 `$`,改用 `locator` 实际上,任何返回 `ElementHandle` 的 API 均[不推荐使用](https://playwright.dev/docs/api/class-page#page-query-selector),包括 `$`、`$$`、`$eval`、`$$eval` 等。[`Locator`](https://playwright.dev/docs/api/class-locator) 是更优秀的 API,可与 Playwright 的[断言功能](https://playwright.dev/docs/api/class-locatorassertions)配合使用。由于定位器采用惰性求值且不返回 Promise,该特性在页面对象模型中表现尤为出色。 ### 使用可访问性选择器 尽可能使用 [`getByRole`](https://playwright.dev/docs/locators#locate-by-role) 构建查询。这样既能编写无障碍查询,又无需依赖内部实现细节: ```js // 选择包含无障碍名称"Hello World"的按钮(不区分大小写) page.getByRole( 'button', { name: 'Hello World' } ); ``` 还支持链式调用以执行复杂查询: ```js // 在"区块库"区域下选择名称为"按钮"的选项 page.getByRole( 'region', { name: 'Block Library' } ) .getByRole( 'option', { name: 'Buttons' } ) ``` 更多使用技巧请参阅[官方文档](https://playwright.dev/docs/locators)。 ### 选择器默认采用严格模式 为提升元素查询的最佳实践,选择器默认启用[严格模式](https://playwright.dev/docs/api/class-browser#browser-new-page-option-strict-selectors),当查询结果包含多个元素时将抛出错误。 ### 避免过度封装测试工具,简单工具应内联实现 `e2e-test-utils` 因包含过多工具函数而变得臃肿。其中大部分函数足够简单,可直接在测试中内联实现。借助可访问性选择器,现在编写简单工具函数更加容易。对于特定页面的工具函数,建议采用页面对象模型(但使用 `requestUtils` 清理状态的情况除外,这类工具更适合放在 `e2e-test-utils` 中)。仅当操作足够复杂且需要重复使用时,才考虑创建工具函数。 ### 优先采用页面对象模型而非工具函数 如前所述,[页面对象模型](https://playwright.dev/docs/pom)是在特定页面创建可复用工具函数的首选方案。 使用页面对象模型的核心优势在于能将工具函数按命名空间分组,更便于发现和使用。实际上,`e2e-test-utils-playwright` 包中的 `PageUtils` 本身就是页面对象模型,既避免了全局变量的使用,又支持通过 `this` 实现工具函数间的相互调用。 ### 通过 REST 接口清理或设置状态 在测试前后手动设置状态效率低下,特别是在测试间需要重复设置时。推荐通过 API 调用来设置状态。请使用 `requestUtils.rest` 和 `requestUtils.batchRest` 调用 [REST API](https://developer.wordpress.org/rest-api/reference/)(如有需要可将其添加到 `requestUtils` 中)。我们仍需为手动设置状态编写测试,但此类测试只需编写一次。 ### 避免使用全局变量 在之前的 Jest + Puppeteer 端到端测试中,`page` 和 `browser` 被暴露为全局变量。当同一测试中涉及多个页面/标签页,或需要并行运行多个测试时,这种方式会使工作变得困难。`@playwright/test` 引入了[测试固件](https://playwright.dev/docs/test-fixtures)概念,允许我们将 `page`、`browser` 及其他参数注入到测试中。 ### 使用显式断言 单个测试中可根据需要插入多个断言。尽可能使用显式断言是更佳实践。例如,若需在点击按钮前确认其存在,可在执行 `locator.click()` 前使用 `expect( locator ).toBeVisible()`。这样能使测试流程更清晰易读。 ## 常见误区 ### [过度使用快照](https://github.com/WordPress/gutenberg/tree/HEAD/docs/contributors/code/e2e/overusing-snapshots.md) ## 跨浏览器测试 默认情况下测试仅在 Chromium 中运行。您可以通过给测试添加标签来指定运行浏览器。在测试标题任意位置使用 `@browser` 即可在对应浏览器中运行测试。默认情况下测试始终会在 Chromium 中运行,可通过添加 `-chromium` 后缀禁用 Chromium 测试。支持的浏览器包括 `chromium`、`firefox` 和 `webkit`。 ```js test( '我将在 @firefox 和 @webkit 中运行(默认包含 chromium)', async ( { page } ) => { // ... } ); test( '我仅在 @firefox 中运行(排除 -chromium)', async ( { page } ) => { // ... } ); test.describe( '测试分组 (@webkit, -chromium)', () => { test( '我仅在 webkit 中运行', async ( { page } ) => { // ... } ); } ); ```