最佳实践
简介
本指南应帮助您确保遵循我们的最佳实践并编写更具弹性的测试。
测试理念
测试用户可见的行为
自动化测试应验证应用程序代码对最终用户是否有效,并避免依赖用户通常不会使用、看不到甚至不知道的实现细节,例如函数名称、某物是否为数组或某个元素的 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.
});
您还可以使用设置项目在测试中重用登录状态。这样,您只需登录一次,然后就可以跳过所有测试的登录步骤。
避免测试第三方依赖项
只测试您控制的内容。不要尝试测试指向您不控制的外部网站或第三方服务器的链接。这不仅会消耗时间并可能减慢测试速度,而且您无法控制链接页面的内容,也无法控制是否存在可能导致测试失败的 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 有一个测试生成器,可以为您生成测试并选择定位器。它会检查您的页面并找出最佳定位器,优先考虑角色、文本和测试 ID 定位器。如果生成器找到与定位器匹配的多个元素,它将改进定位器以使其更具弹性并唯一标识目标元素,因此您不必担心因定位器而导致的测试失败。
使用 codegen 生成定位器
要选择定位器,请运行 codegen 命令,后跟您要从中选择定位器的 URL。
- npm
- yarn
- pnpm
npx playwright codegen playwright.dev
yarn playwright codegen playwright.dev
pnpm exec playwright codegen playwright.dev
这将打开一个新的浏览器窗口以及 Playwright 检查器。要选择定位器,请先单击“记录”按钮以停止录制。默认情况下,当您运行 codegen 命令时,它将开始新的录制。停止录制后,“选择定位器”按钮将可用。您可以点击它。
然后,您可以将鼠标悬停在浏览器窗口中的任何元素上,然后在光标下方看到高亮的定位器。单击元素将在 Playwright 检查器中添加定位器。您可以复制定位器并粘贴到测试文件中,或者继续在 Playwright 检查器中编辑它来探索定位器,例如通过修改文本,并在浏览器窗口中查看结果。
使用 VS Code 扩展生成定位器
您还可以使用VS Code 扩展来生成定位器以及录制测试。VS Code 扩展在编写、运行和调试测试时也为您提供了出色的开发人员体验。
使用面向 Web 的断言
断言是验证预期结果和实际结果是否匹配的一种方式。通过使用面向 Web 的断言,Playwright 将等到满足预期条件。例如,在测试警报消息时,测试将单击一个使消息出现的按钮,并检查警报消息是否存在。如果警报消息需要半秒钟才能出现,诸如 toBeVisible() 这样的断言将等待并在需要时重试。
// 👍
await expect(page.getByText('welcome')).toBeVisible();
// 👎
expect(await page.getByText('welcome').isVisible()).toBe(true);
不要使用手动断言
不要使用没有 await expect 的手动断言。在下面的代码中,await 位于 expect 内部而不是之前。当使用 isVisible() 等断言时,测试不会等待一秒钟,它只会检查定位器是否存在并立即返回。
// 👎
expect(await page.getByText('welcome').isVisible()).toBe(true);
请改用面向 Web 的断言,例如 toBeVisible()。
// 👍
await expect(page.getByText('welcome')).toBeVisible();
配置调试
本地调试
对于本地调试,我们建议您通过安装VS Code 扩展来在 VSCode 中实时调试测试。您可以通过右键单击要运行的测试旁边的行以调试模式运行测试,这将打开一个浏览器窗口并在设置断点的位置暂停。
您可以通过在 VS Code 中单击或编辑测试中的定位器来实时调试测试,这将在浏览器窗口中高亮显示该定位器,并向您显示页面上找到的任何其他匹配的定位器。
您还可以通过运行带有 --debug 标志的测试来使用 Playwright 检查器调试测试。
- npm
- yarn
- pnpm
npx playwright test --debug
yarn playwright test --debug
pnpm exec playwright test --debug
然后,您可以单步执行测试,查看可操作性日志,实时编辑定位器并在浏览器窗口中查看其高亮显示。这将向您显示哪些定位器匹配,以及它们有多少个。
要调试特定测试,请添加测试文件名和测试的行号,后跟 --debug 标志。
- npm
- yarn
- pnpm
npx playwright test example.spec.ts:9 --debug
yarn playwright test example.spec.ts:9 --debug
pnpm exec playwright test example.spec.ts:9 --debug
在 CI 上调试
对于 CI 失败,请使用 Playwright 跟踪查看器而不是视频和屏幕截图。跟踪查看器为您提供测试的完整跟踪,作为一个可以轻松共享的本地渐进式 Web 应用程序 (PWA)。使用跟踪查看器,您可以查看时间轴,使用开发者工具检查每个操作的 DOM 快照,查看网络请求等等。
跟踪是在 Playwright 配置文件中配置的,并设置为在失败测试的第一次重试时在 CI 上运行。我们不建议将其设置为 on,以便对每个测试运行跟踪,因为它对性能要求很高。但是,您可以使用 --trace 标志在本地开发时运行跟踪。
- npm
- yarn
- pnpm
npx playwright test --trace on
yarn playwright test --trace on
pnpm exec playwright test --trace on
运行此命令后,将为每个测试记录跟踪,并可以直接从 HTML 报告中查看。
- npm
- yarn
- pnpm
npx playwright show-report
yarn playwright show-report
pnpm exec playwright show-report
可以通过单击测试文件名旁边的图标或打开每个测试报告并向下滚动到跟踪部分来打开跟踪。
使用 Playwright 的工具
Playwright 附带一系列工具可帮助您编写测试。
- VS Code 扩展在编写、运行和调试测试时为您提供了出色的开发人员体验。
- 测试生成器可以为您生成测试并选择定位器。
- 跟踪查看器为您提供测试的完整跟踪,作为一个可以轻松共享的本地 PWA。使用跟踪查看器,您可以查看时间轴,检查每个操作的 DOM 快照,查看网络请求等等。
- UI 模式允许您以具有“时间旅行”体验和监视模式的方式探索、运行和调试测试。所有测试文件都加载到测试侧边栏中,您可以展开每个文件和 describe 块,以单独运行、查看、监视和调试每个测试。
- Playwright 中的TypeScript开箱即用,为您提供更好的 IDE 集成。您的 IDE 将向您显示所有可以进行的操作,并在您做错事时高亮显示。不需要 TypeScript 经验,也不需要您的代码是 TypeScript 编写的,您需要做的就是使用
.ts扩展名创建测试。
跨所有浏览器进行测试
无论您使用什么平台,Playwright 都可以轻松地在所有浏览器中测试您的网站。跨所有浏览器进行测试可确保您的应用程序对所有用户都正常工作。在您的配置文件中,您可以设置项目,添加名称以及要使用的浏览器或设备。
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
- yarn
- pnpm
npm install -D @playwright/test@latest
yarn add --dev @playwright/test@latest
pnpm install --save-dev @playwright/test@latest
查看发行说明以了解最新版本以及已发布了哪些更改。
您可以通过运行以下命令查看您使用的 Playwright 版本。
- npm
- yarn
- pnpm
npx playwright --version
yarn playwright --version
pnpm exec playwright --version
在 CI 上运行测试
设置 CI/CD 并频繁运行测试。运行测试的频率越高越好。理想情况下,您应该在每次提交和拉取请求时运行测试。Playwright 带有GitHub Actions 工作流,这样测试就可以在 CI 上运行,无需任何设置。您也可以在您选择的CI 环境中设置 Playwright。
在 CI 上运行测试时使用 Linux,因为它更便宜。开发人员可以在本地运行测试时使用任何环境,但在 CI 上使用 Linux。考虑设置分片以加快 CI 速度。
优化 CI 上的浏览器下载
仅安装您实际需要的浏览器,尤其是在 CI 上。例如,如果您只使用 Chromium 进行测试,则只安装 Chromium。
# Instead of installing all browsers
npx playwright install --with-deps
# Install only Chromium
npx playwright install chromium --with-deps
这样可以节省 CI 机器上的下载时间和磁盘空间。
对测试进行 linting
我们推荐在测试中使用 TypeScript 和 ESLint 进行 linting,以尽早发现错误。使用 @typescript-eslint/no-floating-promises ESLint 规则来确保在调用 Playwright API 的异步调用之前没有遗漏 await。在您的 CI 上,您可以运行 tsc --noEmit 以确保函数以正确的签名被调用。
使用并行化和分片
Playwright 默认以并行方式运行测试。单个文件中的测试按顺序在同一个工作进程中运行。如果单个文件中有很多独立测试,您可能希望它们并行运行
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 可以分片测试套件,以便可以在多台机器上执行。
- npm
- yarn
- pnpm
npx playwright test --shard=1/3
yarn playwright test --shard=1/3
pnpm exec playwright test --shard=1/3
提高效率的技巧
使用软断言
如果您的测试失败,Playwright 会给您一个错误消息,显示测试失败的部分,您可以在 VS Code、终端、HTML 报告或跟踪查看器中看到。但是,您也可以使用软断言。这些不会立即终止测试执行,而是在测试结束后编译并显示失败的断言列表。
// 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();