跳转到主要内容

最佳实践

简介

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

测试哲学

测试用户可见的行为

自动化测试应验证应用程序代码对最终用户有效,并避免依赖实现细节,例如用户通常不会使用、看到甚至不知道的东西,例如函数名称、某个东西是否是数组或某个元素的 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。

npx playwright codegen playwright.dev

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

然后,您可以将鼠标悬停在浏览器窗口中页面上的任何元素上,并看到光标下方突出显示的定位器。单击元素会将定位器添加到 Playwright 检查器中。您可以复制定位器并粘贴到您的测试文件中,或者通过在 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);

不要使用手动断言

不要使用未等待期望的手动断言。在下面的代码中,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 跟踪查看器而不是视频和截图。跟踪查看器以本地渐进式 Web 应用程序 (PWA) 的形式为您提供测试的完整跟踪,可以轻松共享。使用跟踪查看器,您可以查看时间轴,使用开发工具检查每个操作的 DOM 快照,查看网络请求等等。

playwrights trace viewer

跟踪在 Playwright 配置文件中配置,并设置为在 CI 上在失败测试的第一次重试时运行。我们不建议将其设置为 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 扩展在编写、运行和调试测试时为您提供出色的开发体验。
  • 测试生成器可以为您生成测试并选择定位器。
  • 跟踪查看器以本地 PWA 的形式为您提供测试的完整跟踪,可以轻松共享。使用跟踪查看器,您可以查看时间轴,检查每个操作的 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 默认并行运行测试。单个文件中的测试按顺序在同一个工作进程中运行。如果您在一个文件中有很多独立的测试,您可能希望并行运行它们。

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 报告或跟踪查看器中看到。但是,您也可以使用软断言。这些断言不会立即终止测试执行,而是在测试结束后编译并显示失败断言的列表。

// 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();