跳到主要内容

最佳实践

简介

本指南应该帮助您确保遵循我们的最佳实践,并编写更具弹性的测试。

测试哲学

测试用户可见的行为

自动化测试应验证应用程序代码对最终用户是否有效,并避免依赖于实现细节,例如用户通常不会使用、看到甚至不知道的东西,例如函数的名称、某物是否是数组或某些元素的 CSS 类。最终用户将看到或与之互动页面上呈现的内容,因此您的测试通常应该只看到/互动相同的呈现输出。

使测试尽可能隔离

每个测试都应与其他测试完全隔离,并应独立运行,具有自己的本地存储、会话存储、数据、Cookie 等。测试隔离提高了可重现性,使调试更容易,并防止级联测试失败。

为了避免重复测试的特定部分,您可以使用 before 和 after 钩子。在您的测试文件中,添加一个 before 钩子以在每个测试之前运行测试的一部分,例如转到特定 URL 或登录到应用程序的某个部分。这保持了测试的隔离性,因为没有测试依赖于另一个测试。但是,当测试足够简单时,稍微重复也是可以的,特别是如果这样做可以使您的测试更清晰、更易于阅读和维护。

import { test } from '@playwright/test';

test.beforeEach(async ({ page }) => {
// Runs before each test and signs in each page.
await page.goto('https://github.com/login');
await page.getByLabel('Username or email address').fill('username');
await page.getByLabel('Password').fill('password');
await page.getByRole('button', { name: 'Sign in' }).click();
});

test('first', async ({ page }) => {
// page is signed in.
});

test('second', async ({ page }) => {
// page is signed in.
});

您还可以使用 setup project 在测试中重用已登录状态。这样,您只需登录一次,然后在所有测试中跳过登录步骤。

避免测试第三方依赖项

仅测试您控制的内容。不要尝试测试指向您不控制的外部网站或第三方服务器的链接。这不仅耗时且会减慢测试速度,而且您也无法控制您链接到的页面的内容,或者是否存在 Cookie 横幅或覆盖页面或任何其他可能导致测试失败的内容。

相反,使用 Playwright Network API 并保证所需的响应。

await page.route('**/api/fetch_data_third_party_dependency', route => route.fulfill({
status: 200,
body: testData,
}));
await page.goto('https://example.com');

使用数据库进行测试

如果使用数据库,请确保您控制数据。针对暂存环境进行测试,并确保它不会更改。对于视觉回归测试,请确保操作系统和浏览器版本相同。

最佳实践

使用定位器

为了编写端到端测试,我们首先需要找到网页上的元素。我们可以通过使用 Playwright 内置的 定位器 来做到这一点。定位器带有自动等待和重试能力。自动等待意味着 Playwright 对元素执行一系列可操作性检查,例如确保元素在执行单击之前是可见和启用的。为了使测试具有弹性,我们建议优先考虑面向用户的属性和显式约定。

// 👍
page.getByRole('button', { name: 'submit' });

使用链式和过滤

定位器可以 链接 以将搜索范围缩小到页面的特定部分。

const product = page.getByRole('listitem').filter({ hasText: 'Product 2' });

您还可以 按文本或另一个定位器过滤定位器

await page
.getByRole('listitem')
.filter({ hasText: 'Product 2' })
.getByRole('button', { name: 'Add to cart' })
.click();

优先使用面向用户的属性而不是 XPath 或 CSS 选择器

您的 DOM 很容易更改,因此让您的测试依赖于您的 DOM 结构可能会导致测试失败。例如,考虑通过其 CSS 类选择此按钮。如果设计师更改了某些内容,则类可能会更改,从而破坏您的测试。

// 👎
page.locator('button.buttonIcon.episode-actions-later');

使用能够适应 DOM 更改的定位器。

// 👍
page.getByRole('button', { name: 'submit' });

生成定位器

Playwright 有一个 测试生成器,可以为您生成测试并选择定位器。它将查看您的页面并找出最佳定位器,优先考虑 role、text 和 test id 定位器。如果生成器找到多个与定位器匹配的元素,它将改进定位器以使其具有弹性并唯一标识目标元素,因此您不必担心由于定位器而导致测试失败。

使用 codegen 生成定位器

要选择定位器,请运行 codegen 命令,后跟您要从中选择定位器的 URL。

npx playwright codegen playwright.dev

这将打开一个新的浏览器窗口以及 Playwright 检查器。要选择定位器,首先单击“Record”按钮以停止录制。默认情况下,当您运行 codegen 命令时,它将开始新的录制。停止录制后,“Pick Locator”按钮将可供单击。

然后,您可以将鼠标悬停在浏览器窗口中页面上的任何元素上,并在光标下方看到突出显示的定位器。单击元素会将定位器添加到 Playwright 检查器中。您可以复制定位器并粘贴到您的测试文件中,或者继续探索定位器,例如通过修改文本,并在浏览器窗口中查看结果。

generating locators with codegen

使用 VS Code 扩展生成定位器

您还可以使用 VS Code 扩展 来生成定位器以及录制测试。VS Code 扩展还在编写、运行和调试测试时为您提供出色的开发者体验。

generating locators in vs code with codegen

使用 Web 优先断言

断言是一种验证预期结果和实际结果是否匹配的方法。通过使用 Web 优先断言,Playwright 将等待直到满足预期条件。例如,在测试警报消息时,测试将单击一个按钮,该按钮会使消息出现,并检查警报消息是否存在。如果警报消息需要半秒钟才能出现,则诸如 toBeVisible() 之类的断言将等待并在需要时重试。

// 👍
await expect(page.getByText('welcome')).toBeVisible();

// 👎
expect(await page.getByText('welcome').isVisible()).toBe(true);

不要使用手动断言

不要使用未等待 expect 的手动断言。在下面的代码中,await 在 expect 内部而不是之前。当使用诸如 isVisible() 之类的断言时,测试不会等待一秒钟,它只会检查定位器是否存在并立即返回。

// 👎
expect(await page.getByText('welcome').isVisible()).toBe(true);

请改用诸如 toBeVisible() 之类的 Web 优先断言。

// 👍
await expect(page.getByText('welcome')).toBeVisible();

配置调试

本地调试

对于本地调试,我们建议您通过安装 VS Code 扩展 在 VSCode 中实时调试您的测试。。您可以通过右键单击要运行的测试旁边的行以调试模式运行测试,这将打开一个浏览器窗口并在设置断点的位置暂停。

debugging tests in vscode

您可以通过在 VS Code 中单击或编辑测试中的定位器来实时调试您的测试,这将突出显示浏览器窗口中的此定位器,并向您显示页面上找到的任何其他匹配定位器。

live debugging locators in vscode

您还可以通过使用 --debug 标志运行测试,使用 Playwright 检查器调试测试。

npx playwright test --debug

然后,您可以单步执行测试,查看可操作性日志并实时编辑定位器,并在浏览器窗口中看到它突出显示。这将向您显示哪些定位器匹配,以及有多少个。

debugging with the playwright inspector

要调试特定测试,请添加测试文件名和测试的行号,后跟 --debug 标志。

npx playwright test example.spec.ts:9 --debug

在 CI 上调试

对于 CI 失败,请使用 Playwright trace viewer 而不是视频和屏幕截图。trace viewer 为您提供测试的完整跟踪,作为一个可以轻松共享的本地渐进式 Web 应用程序 (PWA)。使用 trace viewer,您可以查看时间线,使用开发人员工具检查每个操作的 DOM 快照,查看网络请求等等。

playwrights trace viewer

跟踪在 Playwright 配置文件中配置,并设置为在失败测试的第一次重试时运行。我们不建议将其设置为 on,以便在每次测试时都运行跟踪,因为它非常消耗性能。但是,您可以在开发时使用 --trace 标志在本地运行跟踪。

npx playwright test --trace on

一旦您运行此命令,您的跟踪将被记录在每个测试中,并且可以直接从 HTML 报告中查看。

npx playwright show-report
Playwrights HTML report

可以通过单击测试文件名旁边的图标或打开每个测试报告并向下滚动到跟踪部分来打开跟踪。

Screenshot 2023-01-13 at 09 58 34

使用 Playwright 的工具

Playwright 配备了一系列工具来帮助您编写测试。

  • VS Code 扩展 在编写、运行和调试测试时为您提供出色的开发者体验。
  • 测试生成器 可以为您生成测试并选择定位器。
  • trace viewer 为您提供测试的完整跟踪,作为一个可以轻松共享的本地 PWA。使用 trace viewer,您可以查看时间线,检查每个操作的 DOM 快照,查看网络请求等等。
  • UI 模式 让您可以探索、运行和调试测试,并具有时间旅行体验以及监视模式。所有测试文件都加载到测试侧边栏中,您可以在其中展开每个文件并描述块,以单独运行、查看、监视和调试每个测试。
  • Playwright 中的 TypeScript 开箱即用,并为您提供更好的 IDE 集成。您的 IDE 将向您显示您可以执行的所有操作,并在您做错事时突出显示。不需要 TypeScript 经验,您的代码也不必使用 TypeScript,您只需使用 .ts 扩展名创建测试即可。

跨所有浏览器进行测试

Playwright 使跨所有 浏览器 测试您的站点变得容易,无论您在哪个平台上。跨所有浏览器进行测试可确保您的应用程序对所有用户都有效。在您的配置文件中,您可以设置项目,添加名称以及要使用的浏览器或设备。

playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],
});

保持 Playwright 依赖项为最新

通过保持 Playwright 版本为最新,您将能够在最新的浏览器版本上测试您的应用程序,并在最新的浏览器版本发布给公众之前捕获故障。

npm install -D @playwright/test@latest

查看 发行说明 以查看最新版本是什么以及已发布了哪些更改。

您可以通过运行以下命令查看您拥有的 Playwright 版本。

npx playwright --version

在 CI 上运行测试

设置 CI/CD 并经常运行您的测试。您运行测试的频率越高越好。理想情况下,您应该在每次提交和拉取请求时运行测试。Playwright 配备了 GitHub actions 工作流程,以便测试将在 CI 上为您运行,无需任何设置。Playwright 也可以在您选择的 CI 环境 中设置。

在 CI 上运行测试时使用 Linux,因为它更便宜。开发人员在本地运行时可以使用任何环境,但在 CI 上使用 Linux。考虑设置 分片 以加快 CI 速度。

优化 CI 上的浏览器下载

仅安装您实际需要的浏览器,尤其是在 CI 上。例如,如果您仅使用 Chromium 进行测试,则仅安装 Chromium。

.github/workflows/playwright.yml
# Instead of installing all browsers
npx playwright install --with-deps

# Install only Chromium
npx playwright install chromium --with-deps

这可以节省 CI 机器上的下载时间和磁盘空间。

Lint 您的测试

我们建议为您的测试使用 TypeScript 和 ESLint 进行 linting,以便尽早捕获错误。使用 @typescript-eslint/no-floating-promises ESLint 规则,以确保在对 Playwright API 的异步调用之前没有缺少 await。在您的 CI 上,您可以运行 tsc --noEmit 以确保使用正确的签名调用函数。

使用并行和分片

Playwright 默认以 并行 方式运行测试。单个文件中的测试按顺序在同一 worker 进程中运行。如果单个文件中有很多独立的测试,您可能希望并行运行它们

import { test } from '@playwright/test';

test.describe.configure({ mode: 'parallel' });

test('runs in parallel 1', async ({ page }) => { /* ... */ });
test('runs in parallel 2', async ({ page }) => { /* ... */ });

Playwright 可以 分片 测试套件,以便可以在多台机器上执行它。

npx playwright test --shard=1/3

生产力技巧

使用软断言

如果您的测试失败,Playwright 将给您一个错误消息,显示测试的哪个部分失败,您可以在 VS Code、终端、HTML 报告或 trace viewer 中看到该消息。但是,您也可以使用 软断言。这些断言不会立即终止测试执行,而是在测试结束后编译并显示失败断言的列表。

// Make a few checks that will not stop the test when failed...
await expect.soft(page.getByTestId('status')).toHaveText('Success');

// ... and continue the test to check more things.
await page.getByRole('link', { name: 'next page' }).click();