跳到主要内容

最佳实践

简介

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

测试理念

测试用户可见的行为

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

使测试尽可能隔离

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

为了避免重复测试的特定部分,您可以使用before 和 after hooks。在您的测试文件中添加一个 before hook,以便在每个测试之前运行测试的某一部分,例如转到特定 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 网络 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 检查器中。您可以复制定位器并粘贴到测试文件中,或者继续探索定位器,例如通过在 Playwright 检查器中修改文本,并在浏览器窗口中查看结果。

generating locators with codegen

使用 VS Code 扩展程序生成定位器

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

generating locators in vs code with codegen

使用 Web First 断言

断言是一种验证预期结果和实际结果是否匹配的方法。通过使用Web First 断言,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);

请改用 Web First 断言,例如 toBeVisible()

// 👍
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 的异步调用之前没有遗漏 awaits。在您的 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();