介绍
Playwright 测试基于测试装置的概念。测试夹具用于为每个测试建立环境,为测试提供所需的一切。测试之间的测试夹具是隔离的。使用夹具,你可以根据测试的含义而不是常见的设置对测试进行分组。
内置夹具
你已经在第一次测试中使用了测试装置。
import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => {
await page.goto('https://playwright.nodejs.cn/');
await expect(page).toHaveTitle(/Playwright/);
});
{ page } 参数告诉 Playwright Test 设置 page 夹具并将其提供给你的测试函数。
以下是你大部分时间可能使用的预定义装置的列表:
夹具 类型 描述
page [Page] 此测试运行的独立页面。
context [BrowserContext] 此测试运行的隔离上下文。page 装置也属于这种情况。了解如何 配置上下文。
browser [Browser] 跨测试共享浏览器以优化资源。了解如何 配置浏览器。
browserName [字符串] 当前运行测试的浏览器的名称。chromium、firefox 或 webkit。
request [APIRequestContext] 用于此测试运行的隔离 APIRequestContext 实例。
不使用夹具
以下是传统测试风格和基于夹具的测试风格之间典型测试环境设置的差异。
TodoPage 是一个帮助与 Web 应用的 "待办事项清单" 页面交互的类,遵循 页面对象模型 模式。它内部使用 Playwright 的 page。
todo.spec.ts
const { test } = require('@playwright/test');
const { TodoPage } = require('./todo-page');
test.describe('todo tests', () => {
let todoPage;
test.beforeEach(async ({ page }) => {
todoPage = new TodoPage(page);
await todoPage.goto();
await todoPage.addToDo('item1');
await todoPage.addToDo('item2');
});
test.afterEach(async () => {
await todoPage.removeAll();
});
test('should add an item', async () => {
await todoPage.addToDo('my item');
// ...
});
test('should remove an item', async () => {
await todoPage.remove('item1');
// ...
});
});
使用夹具
与前/后钩子相比,夹具具有许多优点:
Fixtures 将设置和拆卸封装在同一个地方,因此更容易编写。
夹具可以在测试文件之间重复使用 - 你可以定义它们一次并在所有测试中使用。这就是 Playwright 的内置 page 装置的工作原理。
夹具按需提供 - 你可以根据需要定义任意数量的夹具,Playwright Test 将仅设置测试所需的夹具,而不会设置其他任何夹具。
夹具是可组合的 - 它们可以相互依赖来提供复杂的行为。
夹具灵活。测试可以使用夹具的任意组合来定制所需的精确环境,而不会影响其他测试。
夹具简化了分组。你不再需要将测试封装在设置环境的 describe 中,而是可以根据测试的含义自由地对其进行分组。
Click to expand the code for the TodoPage
example.spec.ts
import { test as base } from '@playwright/test';
import { TodoPage } from './todo-page';
// Extend basic test by providing a "todoPage" fixture.
const test = base.extend<{ todoPage: TodoPage }>({
todoPage: async ({ page }, use) => {
const todoPage = new TodoPage(page);
await todoPage.goto();
await todoPage.addToDo('item1');
await todoPage.addToDo('item2');
await use(todoPage);
await todoPage.removeAll();
},
});
test('should add an item', async ({ todoPage }) => {
await todoPage.addToDo('my item');
// ...
});
test('should remove an item', async ({ todoPage }) => {
await todoPage.remove('item1');
// ...
});
创建夹具
要创建你自己的夹具,请使用 test.extend() 创建一个包含它的新 test 对象。
下面我们创建两个遵循 页面对象模型 模式的灯具 todoPage 和 settingsPage。
import { test as base } from '@playwright/test';
import { TodoPage } from './todo-page';
import { SettingsPage } from './settings-page';
// Declare the types of your fixtures.
type MyFixtures = {
todoPage: TodoPage;
settingsPage: SettingsPage;
};
// Extend base test by providing "todoPage" and "settingsPage".
// This new "test" can be used in multiple test files, and each of them will get the fixtures.
export const test = base.extend({
todoPage: async ({ page }, use) => {
// Set up the fixture.
const todoPage = new TodoPage(page);
await todoPage.goto();
await todoPage.addToDo('item1');
await todoPage.addToDo('item2');
// Use the fixture value in the test.
await use(todoPage);
// Clean up the fixture.
await todoPage.removeAll();
},
settingsPage: async ({ page }, use) => {
await use(new SettingsPage(page));
},
});
export { expect } from '@playwright/test';
使用夹具
只需在测试函数参数中提及夹具,测试运行程序就会处理它。夹具还有钩子和其他夹具。如果你使用 TypeScript,灯具将具有正确的类型。
下面我们使用上面定义的 todoPage 和 settingsPage 灯具。
import { test, expect } from './my-test';
test.beforeEach(async ({ settingsPage }) => {
await settingsPage.switchToDarkMode();
});
test('basic test', async ({ todoPage, page }) => {
await todoPage.addToDo('something nice');
await expect(page.getByTestId('todo-title')).toContainText(['something nice']);
});
压倒性的装置
除了创建自己的灯具之外,你还可以覆盖现有的灯具以满足你的需求。考虑以下示例,该示例通过自动导航到某个 baseURL 来覆盖 page 夹具:
import { test as base } from '@playwright/test';
export const test = base.extend({
page: async ({ baseURL, page }, use) => {
await page.goto(baseURL);
await use(page);
},
});
请注意,在此示例中,page 灯具能够依赖其他内置灯具,例如 testOptions.baseURL。我们现在可以在配置文件中配置 baseURL,或者在测试文件中本地配置 test.use()。
example.spec.ts
test.use({ baseURL: 'https://playwright.nodejs.cn' });