Skip to main content

编写测试

介绍

¥Introduction

Playwright 测试很简单,他们

¥Playwright tests are simple, they

  • 执行操作,并且

    ¥perform actions, and

  • 断言状态与预期相反。

    ¥assert the state against expectations.

在执行操作之前不需要等待任何事情:Playwright 在执行每个动作之前会自动等待广泛的 actionability 检查通过。

¥There is no need to wait for anything prior to performing an action: Playwright automatically waits for the wide range of actionability checks to pass prior to performing each action.

执行检查时也无需处理竞争条件 - Playwright 断言的设计方式是描述最终需要满足的期望。

¥There is also no need to deal with the race conditions when performing the checks - Playwright assertions are designed in a way that they describe the expectations that need to be eventually met.

就是这样!这些设计选择让 Playwright 用户完全忘记了测试中的片状超时和活跃检查。

¥That's it! These design choices allow Playwright users to forget about flaky timeouts and racy checks in their tests altogether.

你将学习

¥You will learn

第一次测试

¥First test

看一下下面的示例,了解如何编写测试。

¥Take a look at the following example to see how to write a test.

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

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

// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});

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

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

// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
注意

在 VS Code 中使用 JavaScript 时,在每个测试文件的开头添加 // @ts-check 以获得自动类型检查。

¥Add // @ts-check at the start of each test file when using JavaScript in VS Code to get automatic type checking.

行动

¥Actions

¥Navigation

大多数测试将从将页面导航到 URL 开始。之后,测试将能够与页面元素进行交互。

¥Most of the tests will start with navigating page to the URL. After that, test will be able to interact with the page elements.

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

Playwright 将等待页面达到加载状态,然后再继续。了解有关 page.goto() 选项的更多信息。

¥Playwright will wait for page to reach the load state prior to moving forward. Learn more about the page.goto() options.

交互

¥Interactions

执行操作从定位元素开始。Playwright 为此使用 定位器 API。定位器代表了一种随时在页面上查找元素的方法,了解有关可用定位器 不同种类 的更多信息。Playwright 将在执行操作之前等待元素变为 actionable,因此无需等待它变得可用。

¥Performing actions starts with locating the elements. Playwright uses Locators API for that. Locators represent a way to find element(s) on the page at any moment, learn more about the different types of locators available. Playwright will wait for the element to be actionable prior to performing the action, so there is no need to wait for it to become available.

// Create a locator.
const getStarted = page.getByRole('link', { name: 'Get started' });

// Click it.
await getStarted.click();

大多数情况下,它会写成一行:

¥In most cases, it'll be written in one line:

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

基本动作

¥Basic actions

这是最受欢迎的 Playwright 动作列表。请注意,还有更多内容,因此请务必查看 定位器 API 部分以了解有关它们的更多信息。

¥This is the list of the most popular Playwright actions. Note that there are many more, so make sure to check the Locator API section to learn more about them.

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

断言

¥Assertions

Playwright 以 expect 函数的形式包含 测试断言。要做出断言,请调用 expect(value) 并选择一个反映期望的匹配器。

¥Playwright includes test assertions in the form of expect function. To make an assertion, call expect(value) and choose a matcher that reflects the expectation.

有许多通用匹配器,例如 toEqualtoContaintoBeTruthy,可用于断言任何条件。

¥There are many generic matchers like toEqual, toContain, toBeTruthy that can be used to assert any conditions.

expect(success).toBeTruthy();

Playwright 还包括异步匹配器,它将等待直到满足预期条件。使用这些匹配器可以使测试变得不不稳定且有弹性。例如,此代码将等待,直到页面获取包含 "Playwright" 的标题:

¥Playwright also includes async matchers that will wait until the expected condition is met. Using these matchers allows making the tests non-flaky and resilient. For example, this code will wait until the page gets the title containing "Playwright":

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

以下是最流行的异步断言的列表。请注意,有 还有很多 需要熟悉:

¥Here is the list of the most popular async assertions. Note that there are many more to get familiar with:

断言描述
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

测试隔离

¥Test Isolation

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

¥Playwright Test is based on the concept of test fixtures such as the built in page fixture, which is passed into your test. Pages are isolated between tests due to the Browser Context, which is equivalent to a brand new browser profile, where every test gets a fresh environment, even when multiple tests run in a single Browser.

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

test('example test', async ({ page }) => {
// "page" belongs to an isolated BrowserContext, created for this specific test.
});

test('another test', async ({ page }) => {
// "page" in this second test is completely isolated from the first test.
});

使用测试钩子

¥Using Test Hooks

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

¥You can use various test hooks such as test.describe to declare a group of tests and test.beforeEach and test.afterEach which are executed before/after each test. Other hooks include the test.beforeAll and test.afterAll which are executed once per worker before/after all tests.

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

test.describe('navigation', () => {
test.beforeEach(async ({ page }) => {
// Go to the starting url before each test.
await page.goto('https://playwright.nodejs.cn/');
});

test('main navigation', async ({ page }) => {
// Assertions use the expect API.
await expect(page).toHaveURL('https://playwright.nodejs.cn/');
});
});

下一步是什么

¥What's Next