跳到主要内容

编写测试

简介

Playwright 测试非常简单,它们:

  • 执行操作
  • 验证状态是否符合预期

在执行操作前无需等待任何内容:Playwright 会自动等待各种可操作性检查通过后再执行每个操作。

在执行检查时也无需处理竞态条件 - Playwright 断言的设计方式使其能够描述最终需要满足的预期。

就是这样!这些设计选择让 Playwright 用户完全不必担心测试中的不稳定超时和竞态检查。

你将学习

第一个测试

查看以下示例了解如何编写测试。

tests/example.spec.ts
import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');

// 预期标题"包含"子字符串。
await expect(page).toHaveTitle(/Playwright/);
});

test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');

// 点击"Get started"链接。
await page.getByRole('link', { name: 'Get started' }).click();

// 预期页面有一个名为"Installation"的标题。
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});

:::note
在使用 VS Code 编写 JavaScript 测试文件时,可在文件开头添加 `// @ts-check` 以启用自动类型检查。
:::


## 操作

导航

大多数测试会从导航到指定 URL 开始。之后,测试就可以与页面元素进行交互。

await page.goto('https://playwright.dev/');

Playwright 会等待页面达到加载状态后再继续执行。了解更多关于 page.goto() 的选项。

交互操作

执行操作的第一步是定位元素。Playwright 使用 定位器 API 来实现这一功能。定位器表示在任何时刻都能找到页面上元素的方法,了解更多关于 不同类型 的可用定位器。Playwright 会在执行操作前等待元素变为 可操作状态,因此无需手动等待元素可用。

// 创建一个定位器
const getStarted = page.getByRole('link', { name: 'Get started' });

// 点击它
await getStarted.click();

大多数情况下,可以简写为一行代码:

await page.getByRole('link', { name: 'Get started' }).click();

基础操作

以下是 Playwright 中最常用的操作列表。请注意,实际上还有更多操作,请务必查看 Locator API 部分以了解更多信息。

操作描述
locator.check()勾选输入复选框
locator.click()点击元素
locator.uncheck()取消勾选输入复选框
locator.hover()将鼠标悬停在元素上
locator.fill()填写表单字段,输入文本
locator.focus()聚焦元素
locator.press()按下单个键
locator.setInputFiles()选择要上传的文件
locator.selectOption()在下拉菜单中选择选项

断言

Playwright 以 expect 函数的形式提供了测试断言。要进行断言,调用 expect(value) 并选择一个能反映期望的匹配器。

有许多通用匹配器如 toEqualtoContaintoBeTruthy 可以用来断言任何条件。

expect(success).toBeTruthy();

Playwright 还包含异步匹配器,它们会等待直到满足预期条件。使用这些匹配器可以使测试更加稳定可靠。例如,以下代码会等待页面标题包含"Playwright":

await expect(page).toHaveTitle(/Playwright/);

以下是最常用的异步断言列表。请注意还有更多匹配器可供了解:

断言描述
expect(locator).toBeChecked()复选框被选中
expect(locator).toBeEnabled()控件已启用
expect(locator).toBeVisible()元素可见
expect(locator).toContainText()元素包含文本
expect(locator).toHaveAttribute()元素具有属性
expect(locator).toHaveCount()元素列表具有指定长度
expect(locator).toHaveText()元素匹配文本
expect(locator).toHaveValue()输入元素具有值
expect(page).toHaveTitle()页面具有标题
expect(page).toHaveURL()页面具有URL

测试隔离

Playwright Test 基于测试固件的概念,例如内置的 page 固件,它会传递到你的测试中。由于浏览器上下文的存在,页面在测试之间是隔离的,这相当于一个全新的浏览器配置文件,每个测试都会获得一个全新的环境,即使多个测试在单个浏览器中运行也是如此。

tests/example.spec.ts
import { test } from '@playwright/test';

test('example test', async ({ page }) => {
// "page" 属于一个隔离的 BrowserContext,专为此测试创建
});

test('another test', async ({ page }) => {
// 第二个测试中的 "page" 与第一个测试完全隔离
});

使用测试钩子

你可以使用各种测试钩子,例如 test.describe 来声明一组测试,以及 test.beforeEachtest.afterEach 在每个测试之前/之后执行。其他钩子包括 test.beforeAlltest.afterAll,它们会在所有测试之前/之后每个工作进程执行一次。

tests/example.spec.ts
import { test, expect } from '@playwright/test';

test.describe('navigation', () => {
test.beforeEach(async ({ page }) => {
// 每个测试前跳转到起始 URL
await page.goto('https://playwright.dev/');
});

test('main navigation', async ({ page }) => {
// 断言使用 expect API
await expect(page).toHaveURL('https://playwright.dev/');
});
});

下一步