Playwright Test
Playwright Test 提供了一个 test 函数来声明测试,以及一个 expect 函数来编写断言。
import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => {
await page.goto('https://playwright.net.cn/');
const name = await page.innerText('.navbar__title');
expect(name).toBe('Playwright');
});
方法
test
新增于: v1.10声明一个测试。
test(title, body)test(title, details, body)
用法
import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => {
await page.goto('https://playwright.net.cn/');
// ...
});
标签
你可以通过提供额外的测试详情来标记测试。或者,你可以在测试标题中包含标签。请注意,每个标签必须以 @ 符号开头。
import { test, expect } from '@playwright/test';
test('basic test', {
tag: '@smoke',
}, async ({ page }) => {
await page.goto('https://playwright.net.cn/');
// ...
});
test('another test @smoke', async ({ page }) => {
await page.goto('https://playwright.net.cn/');
// ...
});
测试标签会显示在测试报告中,并且可以通过自定义报告中的 TestCase.tags 属性访问。
你还可以在测试执行期间通过标签过滤测试
- 在 命令行 中;
- 在配置中使用 testConfig.grep 和 testProject.grep;
了解更多关于 标记 的信息。
注解
你可以通过提供额外的测试详情来注解测试。
import { test, expect } from '@playwright/test';
test('basic test', {
annotation: {
type: 'issue',
description: 'https://github.com/microsoft/playwright/issues/23180',
},
}, async ({ page }) => {
await page.goto('https://playwright.net.cn/');
// ...
});
测试注解会显示在测试报告中,并且可以通过自定义报告中的 TestCase.annotations 属性访问。
你也可以在运行时通过操作 testInfo.annotations 来添加注解。
了解更多关于测试注释的信息。
参数
-
测试标题。
-
detailsObject (可选)新增于: v1.42#额外的测试详情。
-
bodyfunction(Fixtures, TestInfo)#测试主体,可以接受一个或两个参数:一个包含 fixtures 的对象和可选的 TestInfo。
test.afterAll
新增于: v1.10声明一个在所有测试执行完毕后、每个 worker 中执行一次的 afterAll hook。
在测试文件的范围内调用时,在文件中的所有测试之后运行。在 test.describe() 组内调用时,在组中的所有测试之后运行。
用法
test.afterAll(async () => {
console.log('Done with tests');
// ...
});
或者,你可以带标题声明一个 hook。
test.afterAll('Teardown', async () => {
console.log('Done with tests');
// ...
});
参数
-
Hook 标题。
-
hookFunctionfunction(Fixtures, TestInfo)#Hook 函数,接受一个或两个参数:一个包含 worker fixtures 的对象和可选的 TestInfo。
详情
添加多个 afterAll hook 时,它们将按注册顺序运行。
请注意,测试失败时工作进程会重启,afterAll hook 会在新 worker 中再次运行。了解更多关于 worker 和失败 的信息。
即使一些 hook 失败,Playwright 也会继续运行所有适用的 hook。
test.afterAll(hookFunction)test.afterAll(title, hookFunction)
test.afterEach
新增于: v1.10声明一个在每个测试之后执行的 afterEach hook。
在测试文件范围内调用时,在文件中的每个测试之后运行。在 test.describe() 组内调用时,在组中的每个测试之后运行。
你可以访问与测试主体本身相同的 Fixtures,以及提供大量有用信息的 TestInfo 对象。例如,你可以检查测试是成功还是失败。
test.afterEach(hookFunction)test.afterEach(title, hookFunction)
用法
import { test, expect } from '@playwright/test';
test.afterEach(async ({ page }) => {
console.log(`Finished ${test.info().title} with status ${test.info().status}`);
if (test.info().status !== test.info().expectedStatus)
console.log(`Did not run as expected, ended up at ${page.url()}`);
});
test('my test', async ({ page }) => {
// ...
});
或者,你可以带标题声明一个 hook。
test.afterEach('Status check', async ({ page }) => {
if (test.info().status !== test.info().expectedStatus)
console.log(`Did not run as expected, ended up at ${page.url()}`);
});
参数
-
Hook 标题。
-
hookFunctionfunction(Fixtures, TestInfo)#Hook 函数,接受一个或两个参数:一个包含 fixtures 的对象和可选的 TestInfo。
详情
添加多个 afterEach hook 时,它们将按注册顺序运行。
即使一些 hook 失败,Playwright 也会继续运行所有适用的 hook。
test.beforeAll
新增于: v1.10声明一个在所有测试之前、每个 worker 进程中只执行一次的 beforeAll hook。
在测试文件范围内调用时,在文件中的所有测试之前运行。在 test.describe() 组内调用时,在组中的所有测试之前运行。
你可以使用 test.afterAll() 来清理在 beforeAll 中设置的任何资源。
test.beforeAll(hookFunction)test.beforeAll(title, hookFunction)
用法
import { test, expect } from '@playwright/test';
test.beforeAll(async () => {
console.log('Before tests');
});
test.afterAll(async () => {
console.log('After tests');
});
test('my test', async ({ page }) => {
// ...
});
或者,你可以带标题声明一个 hook。
test.beforeAll('Setup', async () => {
console.log('Before tests');
});
参数
-
Hook 标题。
-
hookFunctionfunction(Fixtures, TestInfo)#Hook 函数,接受一个或两个参数:一个包含 worker fixtures 的对象和可选的 TestInfo。
详情
添加多个 beforeAll hook 时,它们将按注册顺序运行。
请注意,测试失败时工作进程会重启,beforeAll hook 会在新 worker 中再次运行。了解更多关于 worker 和失败 的信息。
即使一些 hook 失败,Playwright 也会继续运行所有适用的 hook。
test.beforeEach
新增于: v1.10声明一个在每个测试之前执行的 beforeEach hook。
在测试文件范围内调用时,在文件中的每个测试之前运行。在 test.describe() 组内调用时,在组中的每个测试之前运行。
你可以访问与测试主体本身相同的 Fixtures,以及提供大量有用信息的 TestInfo 对象。例如,你可以在开始测试前导航页面。
你可以使用 test.afterEach() 来清理在 beforeEach 中设置的任何资源。
test.beforeEach(hookFunction)test.beforeEach(title, hookFunction)
用法
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
console.log(`Running ${test.info().title}`);
await page.goto('https://my.start.url/');
});
test('my test', async ({ page }) => {
expect(page.url()).toBe('https://my.start.url/');
});
或者,你可以带标题声明一个 hook。
test.beforeEach('Open start URL', async ({ page }) => {
console.log(`Running ${test.info().title}`);
await page.goto('https://my.start.url/');
});
参数
-
Hook 标题。
-
hookFunctionfunction(Fixtures, TestInfo)#Hook 函数,接受一个或两个参数:一个包含 fixtures 的对象和可选的 TestInfo。
详情
添加多个 beforeEach hook 时,它们将按注册顺序运行。
即使一些 hook 失败,Playwright 也会继续运行所有适用的 hook。
test.describe
新增于: v1.10声明一个测试组。
test.describe(title, callback)test.describe(callback)test.describe(title, details, callback)
用法
你可以用标题声明一个测试组。该标题将显示在测试报告中,作为每个测试标题的一部分。
test.describe('two tests', () => {
test('one', async ({ page }) => {
// ...
});
test('two', async ({ page }) => {
// ...
});
});
匿名组
你也可以声明一个没有标题的测试组。这很方便,以便用 test.use() 为一组测试提供共同的选项。
test.describe(() => {
test.use({ colorScheme: 'dark' });
test('one', async ({ page }) => {
// ...
});
test('two', async ({ page }) => {
// ...
});
});
标签
你可以通过提供额外的详情来标记组中的所有测试。请注意,每个标签必须以 @ 符号开头。
import { test, expect } from '@playwright/test';
test.describe('two tagged tests', {
tag: '@smoke',
}, () => {
test('one', async ({ page }) => {
// ...
});
test('two', async ({ page }) => {
// ...
});
});
了解更多关于 标记 的信息。
注解
你可以通过提供额外的详情来注解组中的所有测试。
import { test, expect } from '@playwright/test';
test.describe('two annotated tests', {
annotation: {
type: 'issue',
description: 'https://github.com/microsoft/playwright/issues/23180',
},
}, () => {
test('one', async ({ page }) => {
// ...
});
test('two', async ({ page }) => {
// ...
});
});
了解更多关于测试注释的信息。
参数
-
组标题。
-
detailsObject (可选)新增于: v1.42#组中所有测试的附加详情。
-
在调用 test.describe() 时立即运行的回调函数。在此回调中声明的任何测试都将属于该组。
test.describe.configure
新增于: v1.10配置封闭范围。可以在顶层或在 describe 内部执行。配置适用于整个范围,无论它是在测试声明之前还是之后运行。
在此 处 了解有关并行执行模式的更多信息。
用法
-
并行运行测试。
// Run all the tests in the file concurrently using parallel workers.
test.describe.configure({ mode: 'parallel' });
test('runs in parallel 1', async ({ page }) => {});
test('runs in parallel 2', async ({ page }) => {}); -
按顺序运行测试,独立重试每个失败的测试。
这是默认模式。明确设置它可以覆盖使用
fullyParallel的项目配置,这可能很有用。// Tests in this file run in order. Retries, if any, run independently.
test.describe.configure({ mode: 'default' });
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {}); -
串行运行测试,从头开始重试。如果其中一个串行测试失败,所有后续测试都将被跳过。
注意不建议串行运行。通常最好使测试独立,以便可以独立运行它们。
// Annotate tests as inter-dependent.
test.describe.configure({ mode: 'serial' });
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {}); -
配置每次测试的重试次数和超时。
// Each test in the file will be retried twice and have a timeout of 20 seconds.
test.describe.configure({ retries: 2, timeout: 20_000 });
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {}); -
并行运行多个 describe,但每个 describe 内的测试按顺序运行。
test.describe.configure({ mode: 'parallel' });
test.describe('A, runs in parallel with B', () => {
test.describe.configure({ mode: 'default' });
test('in order A1', async ({ page }) => {});
test('in order A2', async ({ page }) => {});
});
test.describe('B, runs in parallel with A', () => {
test.describe.configure({ mode: 'default' });
test('in order B1', async ({ page }) => {});
test('in order B2', async ({ page }) => {});
});
参数
optionsObject (可选)-
mode"default" | "parallel" | "serial" (可选)#执行模式。在此 处 了解有关执行模式的更多信息。
-
retriesnumber (可选)新增于: v1.28#每个测试的重试次数。
-
每个测试的超时时间(以毫秒为单位)。覆盖 testProject.timeout 和 testConfig.timeout。
-
test.describe.fixme
新增于: v1.25声明一个测试组,类似于 test.describe()。此组中的测试将被标记为“fixme”并且不会被执行。
test.describe.fixme(title, callback)test.describe.fixme(callback)test.describe.fixme(title, details, callback)
用法
test.describe.fixme('broken tests that should be fixed', () => {
test('example', async ({ page }) => {
// This test will not run
});
});
你也可以省略标题。
test.describe.fixme(() => {
// ...
});
参数
-
组标题。
-
detailsObject (可选)新增于: v1.42#有关详细描述,请参阅 test.describe()。
-
在调用 test.describe.fixme() 时立即运行的回调函数。在此回调中添加的任何测试都将属于该组,并且不会运行。
test.describe.only
新增于: v1.10声明一个聚焦的测试组。如果有任何聚焦的测试或套件,将只运行它们,而不会运行其他任何内容。
test.describe.only(title, callback)test.describe.only(callback)test.describe.only(title, details, callback)
用法
test.describe.only('focused group', () => {
test('in the focused group', async ({ page }) => {
// This test will run
});
});
test('not in the focused group', async ({ page }) => {
// This test will not run
});
你也可以省略标题。
test.describe.only(() => {
// ...
});
参数
-
组标题。
-
detailsObject (可选)新增于: v1.42#有关详细描述,请参阅 test.describe()。
-
在调用 test.describe.only() 时立即运行的回调函数。在此回调中添加的任何测试都将属于该组。
test.describe.skip
新增于: v1.10声明一个跳过的测试组,类似于 test.describe()。跳过组中的测试永远不会运行。
test.describe.skip(title, callback)test.describe.skip(title)test.describe.skip(title, details, callback)
用法
test.describe.skip('skipped group', () => {
test('example', async ({ page }) => {
// This test will not run
});
});
你也可以省略标题。
test.describe.skip(() => {
// ...
});
参数
-
组标题。
-
detailsObject (可选)新增于: v1.42#有关详细描述,请参阅 test.describe()。
-
在调用 test.describe.skip() 时立即运行的回调函数。在此回调中添加的任何测试都将属于该组,并且不会运行。
test.extend
新增于: v1.10通过定义 fixtures 和/或可用于测试的选项来扩展 test 对象。
用法
首先定义一个 fixture 和/或一个选项。
- TypeScript
- JavaScript
import { test as base } from '@playwright/test';
import { TodoPage } from './todo-page';
export type Options = { defaultItem: string };
// Extend basic test by providing a "defaultItem" option and a "todoPage" fixture.
export const test = base.extend<Options & { todoPage: TodoPage }>({
// Define an option and provide a default value.
// We can later override it in the config.
defaultItem: ['Do stuff', { option: true }],
// Define a fixture. Note that it can use built-in fixture "page"
// and a new option "defaultItem".
todoPage: async ({ page, defaultItem }, use) => {
const todoPage = new TodoPage(page);
await todoPage.goto();
await todoPage.addToDo(defaultItem);
await use(todoPage);
await todoPage.removeAll();
},
});
const base = require('@playwright/test');
const { TodoPage } = require('./todo-page');
// Extend basic test by providing a "defaultItem" option and a "todoPage" fixture.
exports.test = base.test.extend({
// Define an option and provide a default value.
// We can later override it in the config.
defaultItem: ['Do stuff', { option: true }],
// Define a fixture. Note that it can use built-in fixture "page"
// and a new option "defaultItem".
todoPage: async ({ page, defaultItem }, use) => {
const todoPage = new TodoPage(page);
await todoPage.goto();
await todoPage.addToDo(defaultItem);
await use(todoPage);
await todoPage.removeAll();
},
});
然后在测试中使用 fixture。
import { test } from './my-test';
test('test 1', async ({ todoPage }) => {
await todoPage.addToDo('my todo');
// ...
});
在配置文件中配置选项。
- TypeScript
- JavaScript
import { defineConfig } from '@playwright/test';
import type { Options } from './my-test';
export default defineConfig<Options>({
projects: [
{
name: 'shopping',
use: { defaultItem: 'Buy milk' },
},
{
name: 'wellbeing',
use: { defaultItem: 'Exercise!' },
},
]
});
// @ts-check
module.exports = defineConfig({
projects: [
{
name: 'shopping',
use: { defaultItem: 'Buy milk' },
},
{
name: 'wellbeing',
use: { defaultItem: 'Exercise!' },
},
]
});
参数
-
包含 fixtures 和/或选项的对象。了解更多关于 fixtures 格式 的信息。
返回
test.fail
新增于: v1.10将测试标记为“应失败”。Playwright 运行此测试并确保它确实失败了。这对于记录已知存在错误的功能直到修复为止非常有用。
声明一个“失败”测试
test.fail(title, body)test.fail(title, details, body)
在运行时注解测试为“失败”
test.fail(condition, description)test.fail(callback, description)test.fail()
用法
你可以将测试声明为失败,以便 Playwright 确保它确实失败了。
import { test, expect } from '@playwright/test';
test.fail('not yet ready', async ({ page }) => {
// ...
});
如果你的测试在某些配置中失败,但在其他配置中没有,你可以根据某个条件在测试主体内将测试标记为失败。在这种情况下,我们建议传递一个 description 参数。
import { test, expect } from '@playwright/test';
test('fail in WebKit', async ({ page, browserName }) => {
test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet');
// ...
});
你可以使用单个 test.fail(callback, description) 调用,根据某个条件将文件或 test.describe() 组中的所有测试标记为“应失败”。
import { test, expect } from '@playwright/test';
test.fail(({ browserName }) => browserName === 'webkit', 'not implemented yet');
test('fail in WebKit 1', async ({ page }) => {
// ...
});
test('fail in WebKit 2', async ({ page }) => {
// ...
});
你也可以在测试主体内调用不带参数的 test.fail() 以始终将测试标记为失败。我们建议使用 test.fail(title, body) 代替。
import { test, expect } from '@playwright/test';
test('less readable', async ({ page }) => {
test.fail();
// ...
});
参数
-
测试标题。
-
detailsObject (可选)新增于: v1.42#有关测试详情描述,请参阅 test()。
-
bodyfunction(Fixtures, TestInfo) (可选)新增于: v1.42#测试主体,可以接受一个或两个参数:一个包含 fixtures 的对象和可选的 TestInfo。
-
当条件为
true时,测试被标记为“应失败”。 -
callbackfunction(Fixtures):boolean (可选)#一个函数,根据测试 fixtures 返回是否应标记为“应失败”。当返回值是
true时,测试被标记为“应失败”。 -
可选描述,将反映在测试报告中。
test.fail.only
新增于: v1.49你可以使用 test.fail.only 来聚焦于一个预期失败的特定测试。这在调试失败的测试或处理特定问题时特别有用。
声明一个聚焦的“失败”测试
test.fail.only(title, body)test.fail.only(title, details, body)
用法
你可以声明一个聚焦的失败测试,以便 Playwright 只运行此测试并确保它确实失败了。
import { test, expect } from '@playwright/test';
test.fail.only('focused failing test', async ({ page }) => {
// This test is expected to fail
});
test('not in the focused group', async ({ page }) => {
// This test will not run
});
参数
-
测试标题。
-
有关测试详情描述,请参阅 test.describe()。
-
bodyfunction(Fixtures, TestInfo) (可选)#测试主体,可以接受一个或两个参数:一个包含 fixtures 的对象和可选的 TestInfo。
test.fixme
新增于: v1.10将测试标记为“待修复”,意在修复它。Playwright 不会在 test.fixme() 调用之后运行该测试。
声明一个“待修复”测试
test.fixme(title, body)test.fixme(title, details, body)
在运行时注解测试为“待修复”
test.fixme(condition, description)test.fixme(callback, description)test.fixme()
用法
你可以将测试声明为待修复,Playwright 将不会运行它。
import { test, expect } from '@playwright/test';
test.fixme('to be fixed', async ({ page }) => {
// ...
});
如果你的测试在某些配置中应该被修复,但在其他配置中不应该,你可以根据某个条件在测试主体内将测试标记为“待修复”。在这种情况下,我们建议传递一个 description 参数。Playwright 将运行测试,但在 test.fixme 调用后立即中止它。
import { test, expect } from '@playwright/test';
test('to be fixed in Safari', async ({ page, browserName }) => {
test.fixme(browserName === 'webkit', 'This feature breaks in Safari for some reason');
// ...
});
你可以使用单个 test.fixme(callback, description) 调用,根据某个条件将文件或 test.describe() 组中的所有测试标记为“待修复”。
import { test, expect } from '@playwright/test';
test.fixme(({ browserName }) => browserName === 'webkit', 'Should figure out the issue');
test('to be fixed in Safari 1', async ({ page }) => {
// ...
});
test('to be fixed in Safari 2', async ({ page }) => {
// ...
});
你也可以在测试主体内调用不带参数的 test.fixme() 以始终将测试标记为失败。我们建议使用 test.fixme(title, body) 代替。
import { test, expect } from '@playwright/test';
test('less readable', async ({ page }) => {
test.fixme();
// ...
});
参数
-
测试标题。
-
detailsObject (可选)新增于: v1.42#有关测试详情描述,请参阅 test()。
-
bodyfunction(Fixtures, TestInfo) (可选)#测试主体,可以接受一个或两个参数:一个包含 fixtures 的对象和可选的 TestInfo。
-
当条件为
true时,测试被标记为“待修复”。 -
callbackfunction(Fixtures):boolean (可选)#一个函数,根据测试 fixtures 返回是否应标记为“待修复”。当返回值是
true时,测试被标记为“待修复”。 -
可选描述,将反映在测试报告中。
test.info
新增于: v1.10返回有关当前正在运行的测试的信息。此方法只能在测试执行期间调用,否则会抛出错误。
用法
test('example test', async ({ page }) => {
// ...
await test.info().attach('screenshot', {
body: await page.screenshot(),
contentType: 'image/png',
});
});
返回
test.only
新增于: v1.10声明一个聚焦的测试。如果有任何聚焦的测试或套件,将只运行它们,而不会运行其他任何内容。
test.only(title, body)test.only(title, details, body)
用法
test.only('focus this test', async ({ page }) => {
// Run only focused tests in the entire project.
});
参数
-
测试标题。
-
detailsObject (可选)新增于: v1.42#有关测试详情描述,请参阅 test()。
-
bodyfunction(Fixtures, TestInfo)#测试主体,可以接受一个或两个参数:一个包含 fixtures 的对象和可选的 TestInfo。
test.setTimeout
新增于: v1.10更改测试的超时时间。零表示没有超时。了解更多关于 各种超时 的信息。
当前运行测试的超时时间可通过 testInfo.timeout 访问。
用法
-
更改测试超时。
test('very slow test', async ({ page }) => {
test.setTimeout(120000);
// ...
}); -
从慢速的
beforeEachhook 更改超时。请注意,这会影响与beforeEachhook 共享的测试超时。test.beforeEach(async ({ page }, testInfo) => {
// Extend timeout for all tests running this hook by 30 seconds.
test.setTimeout(testInfo.timeout + 30000);
}); -
更改
beforeAll或afterAllhook 的超时时间。请注意,这会影响 hook 的超时时间,而不是测试的超时时间。test.beforeAll(async () => {
// Set timeout for this hook.
test.setTimeout(60000);
}); -
更改 test.describe() 组中所有测试的超时时间。
test.describe('group', () => {
// Applies to all tests in this group.
test.describe.configure({ timeout: 60000 });
test('test one', async () => { /* ... */ });
test('test two', async () => { /* ... */ });
test('test three', async () => { /* ... */ });
});
参数
test.skip
新增于: v1.10跳过一个测试。Playwright 不会在 test.skip() 调用之后运行该测试。
跳过的测试不应该被运行。如果你打算修复测试,请使用 test.fixme() 代替。
声明一个跳过的测试
test.skip(title, body)test.skip(title, details, body)
在运行时跳过一个测试
test.skip(condition, description)test.skip(callback, description)test.skip()
用法
你可以声明一个跳过的测试,Playwright 将不会运行它。
import { test, expect } from '@playwright/test';
test.skip('never run', async ({ page }) => {
// ...
});
如果你的测试在某些配置中应该被跳过,但在其他配置中不应该,你可以根据某个条件在测试主体内跳过测试。在这种情况下,我们建议传递一个 description 参数。Playwright 将运行测试,但在 test.skip 调用后立即中止它。
import { test, expect } from '@playwright/test';
test('Safari-only test', async ({ page, browserName }) => {
test.skip(browserName !== 'webkit', 'This feature is Safari-only');
// ...
});
你可以使用单个 test.skip(callback, description) 调用,根据某个条件跳过文件或 test.describe() 组中的所有测试。
import { test, expect } from '@playwright/test';
test.skip(({ browserName }) => browserName !== 'webkit', 'Safari-only');
test('Safari-only test 1', async ({ page }) => {
// ...
});
test('Safari-only test 2', async ({ page }) => {
// ...
});
你也可以在测试主体内调用不带参数的 test.skip() 以始终跳过测试。但是,我们建议使用 test.skip(title, body) 代替。
import { test, expect } from '@playwright/test';
test('less readable', async ({ page }) => {
test.skip();
// ...
});
参数
-
测试标题。
-
detailsObject (可选)新增于: v1.42#有关测试详情描述,请参阅 test()。
-
bodyfunction(Fixtures, TestInfo) (可选)#测试主体,可以接受一个或两个参数:一个包含 fixtures 的对象和可选的 TestInfo。
-
当条件为
true时,测试被标记为“已跳过”。 -
callbackfunction(Fixtures):boolean (可选)#一个函数,返回是否应标记为“已跳过”,基于测试 fixtures。当返回值是
true时,测试被标记为“已跳过”。 -
可选描述,将反映在测试报告中。
test.slow
新增于: v1.10将测试标记为“慢速”。慢速测试将获得默认超时时间的三倍。
请注意,beforeAll 或 afterAll 钩子中不能使用 test.slow()。请改用 test.setTimeout()。
test.slow()test.slow(condition, description)test.slow(callback, description)
用法
您可以通过在测试主体中调用 test.slow() 将测试标记为慢速。
import { test, expect } from '@playwright/test';
test('slow test', async ({ page }) => {
test.slow();
// ...
});
如果您的测试在某些配置下很慢,但在其他配置下不慢,您可以根据条件将其标记为慢速。在这种情况下,我们建议提供一个 description 参数。
import { test, expect } from '@playwright/test';
test('slow in Safari', async ({ page, browserName }) => {
test.slow(browserName === 'webkit', 'This feature is slow in Safari');
// ...
});
您可以通过传递一个回调函数,根据某些条件将文件或 test.describe() 组中的所有测试标记为“慢速”。
import { test, expect } from '@playwright/test';
test.slow(({ browserName }) => browserName === 'webkit', 'all tests are slow in Safari');
test('slow in Safari 1', async ({ page }) => {
// ...
});
test('fail in Safari 2', async ({ page }) => {
// ...
});
参数
-
当条件为
true时,测试被标记为“慢速”。 -
callback函数(Fixtures):布尔值 (可选)#一个返回是否应标记为“慢速”的函数,基于测试夹具。当返回值是
true时,测试被标记为“慢速”。 -
可选描述,将反映在测试报告中。
test.step
新增于: v1.10声明一个在报告中显示的测试步骤。
用法
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await test.step('Log in', async () => {
// ...
});
await test.step('Outer step', async () => {
// ...
// You can nest steps inside each other.
await test.step('Inner step', async () => {
// ...
});
});
});
参数
-
步骤名称。
-
body函数(TestStepInfo):Promise<Object>#步骤主体。
-
optionsObject (可选)-
是否在报告中将步骤装箱。默认为
false。当步骤被装箱时,从步骤内部抛出的错误会指向步骤调用站点。有关更多详细信息,请参见下文。 -
在测试报告和跟踪查看器中指定步骤的自定义位置。默认情况下,显示 test.step() 调用的位置。
-
允许步骤完成的最大时间(以毫秒为单位)。如果步骤未在指定超时内完成,test.step() 方法将抛出 TimeoutError。默认为
0(无超时)。
-
返回
详情
该方法返回步骤回调返回的值。
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
const user = await test.step('Log in', async () => {
// ...
return 'john';
});
expect(user).toBe('john');
});
装饰器
您可以使用 TypeScript 方法装饰器将方法转换为步骤。对装饰方法进行每次调用都会在报告中显示为一个步骤。
function step(target: Function, context: ClassMethodDecoratorContext) {
return function replacementMethod(...args: any) {
const name = this.constructor.name + '.' + (context.name as string);
return test.step(name, async () => {
return await target.call(this, ...args);
}, { box: true });
};
}
class LoginPage {
constructor(readonly page: Page) {}
@step
async login() {
const account = { username: 'Alice', password: 's3cr3t' };
await this.page.getByLabel('Username or email address').fill(account.username);
await this.page.getByLabel('Password').fill(account.password);
await this.page.getByRole('button', { name: 'Sign in' }).click();
await expect(this.page.getByRole('button', { name: 'View profile and more' })).toBeVisible();
}
}
test('example', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.login();
});
装箱
当步骤内的某个地方失败时,您通常会看到错误指向失败的确切操作。例如,考虑以下登录步骤
async function login(page) {
await test.step('login', async () => {
const account = { username: 'Alice', password: 's3cr3t' };
await page.getByLabel('Username or email address').fill(account.username);
await page.getByLabel('Password').fill(account.password);
await page.getByRole('button', { name: 'Sign in' }).click();
await expect(page.getByRole('button', { name: 'View profile and more' })).toBeVisible();
});
}
test('example', async ({ page }) => {
await page.goto('https://github.com/login');
await login(page);
});
Error: Timed out 5000ms waiting for expect(locator).toBeVisible()
... error details omitted ...
8 | await page.getByRole('button', { name: 'Sign in' }).click();
> 9 | await expect(page.getByRole('button', { name: 'View profile and more' })).toBeVisible();
| ^
10 | });
如上所示,测试可能会因指向步骤内部的错误而失败。如果您希望错误突出显示“login”步骤而不是其内部,请使用 box 选项。装箱步骤内的错误会指向步骤调用站点。
async function login(page) {
await test.step('login', async () => {
// ...
}, { box: true }); // Note the "box" option here.
}
Error: Timed out 5000ms waiting for expect(locator).toBeVisible()
... error details omitted ...
14 | await page.goto('https://github.com/login');
> 15 | await login(page);
| ^
16 | });
您也可以创建一个类似于上述常规步骤装饰器的装箱步骤的 TypeScript 装饰器
function boxedStep(target: Function, context: ClassMethodDecoratorContext) {
return function replacementMethod(...args: any) {
const name = this.constructor.name + '.' + (context.name as string);
return test.step(name, async () => {
return await target.call(this, ...args);
}, { box: true }); // Note the "box" option here.
};
}
class LoginPage {
constructor(readonly page: Page) {}
@boxedStep
async login() {
// ....
}
}
test('example', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.login(); // <-- Error will be reported on this line.
});
test.step.skip
新增于: v1.50将测试步骤标记为“跳过”,以临时禁用其执行,这对于当前失败并计划在短期内修复的步骤很有用。Playwright 不会运行该步骤。另请参阅 testStepInfo.skip()。
我们建议改用 testStepInfo.skip()。
用法
您可以声明一个跳过的步骤,Playwright 将不会运行它。
import { test, expect } from '@playwright/test';
test('my test', async ({ page }) => {
// ...
await test.step.skip('not yet ready', async () => {
// ...
});
});
参数
-
步骤名称。
-
步骤主体。
-
optionsObject (可选)
返回
test.use
新增于: v1.10指定在单个测试文件或 test.describe() 组中使用的选项或夹具。最常用于设置选项,例如设置 locale 以配置 context 夹具。
用法
import { test, expect } from '@playwright/test';
test.use({ locale: 'en-US' });
test('test with locale', async ({ page }) => {
// Default context and page have locale as specified
});
参数
-
optionsTestOptions#一个包含本地选项的对象。
详情
test.use 可以在全局作用域或 test.describe 内部调用。在 beforeEach 或 beforeAll 中调用它是错误的。
也可以通过提供一个函数来覆盖夹具。
import { test, expect } from '@playwright/test';
test.use({
locale: async ({}, use) => {
// Read locale from some configuration file.
const locale = await fs.promises.readFile('test-locale', 'utf-8');
await use(locale);
},
});
test('test with locale', async ({ page }) => {
// Default context and page have locale as specified
});
属性
test.expect
新增于: v1.10expect 函数可用于创建测试断言。阅读有关 测试断言 的更多信息。
用法
test('example', async ({ page }) => {
await test.expect(page).toHaveTitle('Title');
});
类型
已弃用
test.describe.parallel
新增于: v1.10请参阅 test.describe.configure() 以了解配置执行模式的首选方法。
声明一组可以并行运行的测试。默认情况下,单个测试文件中的测试会一个接一个地运行,但使用 test.describe.parallel() 可以让它们并行运行。
test.describe.parallel(title, callback)test.describe.parallel(callback)test.describe.parallel(title, details, callback)
用法
test.describe.parallel('group', () => {
test('runs in parallel 1', async ({ page }) => {});
test('runs in parallel 2', async ({ page }) => {});
});
请注意,并行测试在单独的进程中执行,不能共享任何状态或全局变量。每个并行测试都会执行所有相关的钩子。
你也可以省略标题。
test.describe.parallel(() => {
// ...
});
参数
-
组标题。
-
detailsObject (可选)新增于: v1.42#有关详细描述,请参阅 test.describe()。
-
调用 test.describe.parallel() 时立即运行的回调函数。在此回调中添加的任何测试都将属于该组。
test.describe.parallel.only
新增于: v1.10请参阅 test.describe.configure() 以了解配置执行模式的首选方法。
声明一个可以并行运行的重点测试组。这类似于 test.describe.parallel(),但重点在于该组。如果有任何重点测试或套件,将运行所有这些测试,但不会运行其他任何内容。
test.describe.parallel.only(title, callback)test.describe.parallel.only(callback)test.describe.parallel.only(title, details, callback)
用法
test.describe.parallel.only('group', () => {
test('runs in parallel 1', async ({ page }) => {});
test('runs in parallel 2', async ({ page }) => {});
});
你也可以省略标题。
test.describe.parallel.only(() => {
// ...
});
参数
-
组标题。
-
detailsObject (可选)新增于: v1.42#有关详细描述,请参阅 test.describe()。
-
调用 test.describe.parallel.only() 时立即运行的回调函数。在此回调中添加的任何测试都将属于该组。
test.describe.serial
新增于: v1.10请参阅 test.describe.configure() 以了解配置执行模式的首选方法。
声明一个应始终串行运行的测试组。如果其中一个测试失败,所有后续测试都将被跳过。组中的所有测试会一起重试。
不建议使用串行模式。通常最好使您的测试相互隔离,以便可以独立运行它们。
test.describe.serial(title, callback)test.describe.serial(title)test.describe.serial(title, details, callback)
用法
test.describe.serial('group', () => {
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {});
});
你也可以省略标题。
test.describe.serial(() => {
// ...
});
参数
-
组标题。
-
detailsObject (可选)新增于: v1.42#有关详细描述,请参阅 test.describe()。
-
调用 test.describe.serial() 时立即运行的回调函数。在此回调中添加的任何测试都将属于该组。
test.describe.serial.only
新增于: v1.10请参阅 test.describe.configure() 以了解配置执行模式的首选方法。
声明一个应始终串行运行的重点测试组。如果其中一个测试失败,所有后续测试都将被跳过。组中的所有测试会一起重试。如果有任何重点测试或套件,将运行所有这些测试,但不会运行其他任何内容。
不建议使用串行模式。通常最好使您的测试相互隔离,以便可以独立运行它们。
test.describe.serial.only(title, callback)test.describe.serial.only(title)test.describe.serial.only(title, details, callback)
用法
test.describe.serial.only('group', () => {
test('runs first', async ({ page }) => {
});
test('runs second', async ({ page }) => {
});
});
你也可以省略标题。
test.describe.serial.only(() => {
// ...
});
参数