Skip to main content

Playwright 测试

Playwright 测试提供了 test 函数用于声明测试,expect 函数用于编写断言。

🌐 Playwright Test provides a test function to declare tests and expect function to write assertions.

import { test, expect } from '@playwright/test';

test('basic test', async ({ page }) => {
await page.goto('https://playwright.nodejs.cn/');
const name = await page.innerText('.navbar__title');
expect(name).toBe('Playwright');
});

方法

🌐 Methods

test

Added in: v1.10 test.test

宣布进行测试。

🌐 Declares a test.

  • test(title, body)
  • test(title, details, body)

用法

import { test, expect } from '@playwright/test';

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

标签

你可以通过提供额外的测试详情来为测试添加标签。或者,你也可以在测试标题中包含标签。请注意,每个标签必须以 @ 符号开头。

🌐 You can tag tests by providing additional test details. Alternatively, you can include tags in the test title. Note that each tag must start with @ symbol.

import { test, expect } from '@playwright/test';

test('basic test', {
tag: '@smoke',
}, async ({ page }) => {
await page.goto('https://playwright.nodejs.cn/');
// ...
});

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

测试标签会显示在测试报告中,并且可以通过 TestCase.tags 属性供自定义报告使用。

🌐 Test tags are displayed in the test report, and are available to a custom reporter via TestCase.tags property.

你还可以在测试执行期间按标签过滤测试:

🌐 You can also filter tests by their tags during test execution:

了解有关tagging的更多信息。

🌐 Learn more about tagging.

注释

你可以通过提供额外的测试详细信息来注释测试。

🌐 You can annotate tests by providing additional test details.

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.nodejs.cn/');
// ...
});

测试注释显示在测试报告中,并且可以通过 TestCase.annotations 属性供自定义报告使用。

🌐 Test annotations are displayed in the test report, and are available to a custom reporter via TestCase.annotations property.

你也可以在运行时通过操作 testInfo.annotations 来添加注释。

🌐 You can also add annotations during runtime by manipulating testInfo.annotations.

了解有关 测试注释 的更多信息。

🌐 Learn more about test annotations.

参数


test.afterAll

Added in: v1.10 test.test.afterAll

声明一个 afterAll 钩子,在所有测试之后每个工作进程执行一次。

🌐 Declares an afterAll hook that is executed once per worker after all tests.

在测试文件范围内调用时,会在文件中的所有测试之后运行。 在test.describe()组内调用时,会在组内的所有测试之后运行。

🌐 When called in the scope of a test file, runs after all tests in the file. When called inside a test.describe() group, runs after all tests in the group.

用法

test.afterAll(async () => {
console.log('Done with tests');
// ...
});

或者,你可以声明一个 带标题 的钩子。

🌐 Alternatively, you can declare a hook with a title.

test.afterAll('Teardown', async () => {
console.log('Done with tests');
// ...
});

参数

  • title string (optional) Added in: v1.38#

    钩子标题。

  • hookFunction function(Fixtures, TestInfo)#

    钩子函数,接受一个或两个参数:一个包含工作器夹具的对象和可选的 TestInfo

详情

当添加多个 afterAll 钩子时,它们将按注册顺序运行。

🌐 When multiple afterAll hooks are added, they will run in the order of their registration.

请注意,工作进程在测试失败时会重新启动,并且 afterAll 钩子会在新的工作进程中再次运行。了解更多关于工作进程和失败的信息。

🌐 Note that worker process is restarted on test failures, and afterAll hook runs again in the new worker. Learn more about workers and failures.

Playwright 将继续运行所有适用的钩子,即使其中一些钩子失败。

🌐 Playwright will continue running all applicable hooks even if some of them have failed.

  • test.afterAll(hookFunction)
  • test.afterAll(title, hookFunction)

test.afterEach

Added in: v1.10 test.test.afterEach

声明一个 afterEach 钩子,该钩子会在每个测试之后执行。

🌐 Declares an afterEach hook that is executed after each test.

在测试文件范围内调用时,会在文件中的每个测试之后运行。在test.describe()组内调用时,会在组中的每个测试之后运行。

🌐 When called in the scope of a test file, runs after each test in the file. When called inside a test.describe() group, runs after each test in the group.

你可以访问与测试主体本身相同的所有Fixtures,还可以访问提供许多有用信息的TestInfo对象。例如,你可以检查测试是成功还是失败。

🌐 You can access all the same Fixtures as the test body itself, and also the TestInfo object that gives a lot of useful information. For example, you can check whether the test succeeded or failed.

  • test.afterEach(hookFunction)
  • test.afterEach(title, hookFunction)

用法

example.spec.ts
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 }) => {
// ...
});

或者,你可以声明一个 带标题 的钩子。

🌐 Alternatively, you can declare a hook with a title.

example.spec.ts
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()}`);
});

参数

详情

当添加多个 afterEach 钩子时,它们将按注册顺序运行。

🌐 When multiple afterEach hooks are added, they will run in the order of their registration.

Playwright 将继续运行所有适用的钩子,即使其中一些钩子失败。

🌐 Playwright will continue running all applicable hooks even if some of them have failed.


test.beforeAll

Added in: v1.10 test.test.beforeAll

声明一个 beforeAll 钩子,该钩子在每个工作进程中在所有测试之前执行一次。

🌐 Declares a beforeAll hook that is executed once per worker process before all tests.

在测试文件的范围内调用时,会在文件中的所有测试之前运行。 在test.describe() 组内调用时,会在组内的所有测试之前运行。

🌐 When called in the scope of a test file, runs before all tests in the file. When called inside a test.describe() group, runs before all tests in the group.

你可以使用 test.afterAll() 来清理在 beforeAll 中设置的任何资源。

🌐 You can use test.afterAll() to teardown any resources set up in beforeAll.

  • test.beforeAll(hookFunction)
  • test.beforeAll(title, hookFunction)

用法

example.spec.ts
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 }) => {
// ...
});

或者,你可以声明一个 带标题 的钩子。

🌐 Alternatively, you can declare a hook with a title.

example.spec.ts
test.beforeAll('Setup', async () => {
console.log('Before tests');
});

参数

  • title string (optional) Added in: v1.38#

    钩子标题。

  • hookFunction function(Fixtures, TestInfo)#

    钩子函数,接受一个或两个参数:一个包含工作器夹具的对象和可选的 TestInfo

详情

当添加多个 beforeAll 钩子时,它们将按注册顺序运行。

🌐 When multiple beforeAll hooks are added, they will run in the order of their registration.

请注意,工作进程在测试失败时会重新启动,并且 beforeAll 钩子会在新的工作进程中再次运行。了解更多关于工作进程和失败的信息。

🌐 Note that worker process is restarted on test failures, and beforeAll hook runs again in the new worker. Learn more about workers and failures.

Playwright 将继续运行所有适用的钩子,即使其中一些钩子失败。

🌐 Playwright will continue running all applicable hooks even if some of them have failed.


test.beforeEach

Added in: v1.10 test.test.beforeEach

声明一个 beforeEach 钩子,该钩子会在每个测试之前执行。

🌐 Declares a beforeEach hook that is executed before each test.

在测试文件的范围内调用时,会在文件中的每个测试之前运行。 当在 test.describe() 组内调用时,会在组内的每个测试之前运行。

🌐 When called in the scope of a test file, runs before each test in the file. When called inside a test.describe() group, runs before each test in the group.

你可以访问与测试主体本身相同的所有Fixtures,还可以访问提供许多有用信息的TestInfo对象。例如,你可以在开始测试之前浏览页面。

🌐 You can access all the same Fixtures as the test body itself, and also the TestInfo object that gives a lot of useful information. For example, you can navigate the page before starting the test.

你可以使用 test.afterEach() 来清理在 beforeEach 中设置的任何资源。

🌐 You can use test.afterEach() to teardown any resources set up in beforeEach.

  • test.beforeEach(hookFunction)
  • test.beforeEach(title, hookFunction)

用法

example.spec.ts
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/');
});

或者,你可以声明一个 带标题 的钩子。

🌐 Alternatively, you can declare a hook with a title.

example.spec.ts
test.beforeEach('Open start URL', async ({ page }) => {
console.log(`Running ${test.info().title}`);
await page.goto('https://my.start.url/');
});

参数

详情

当添加多个 beforeEach 钩子时,它们将按注册顺序运行。

🌐 When multiple beforeEach hooks are added, they will run in the order of their registration.

Playwright 将继续运行所有适用的钩子,即使其中一些钩子失败。

🌐 Playwright will continue running all applicable hooks even if some of them have failed.


test.describe

Added in: v1.10 test.test.describe

声明一组测试。

🌐 Declares a group of tests.

  • test.describe(title, callback)
  • test.describe(callback)
  • test.describe(title, details, callback)

用法

你可以使用标题来声明一组测试。该标题将在测试报告中作为每个测试标题的一部分显示。

🌐 You can declare a group of tests with a title. The title will be visible in the test report as a part of each test's title.

test.describe('two tests', () => {
test('one', async ({ page }) => {
// ...
});

test('two', async ({ page }) => {
// ...
});
});

匿名组

你也可以声明一个没有标题的测试组。这对于用 test.use() 给一组测试设置共同选项非常方便。

🌐 You can also declare a test group without a title. This is convenient to give a group of tests a common option with test.use().

test.describe(() => {
test.use({ colorScheme: 'dark' });

test('one', async ({ page }) => {
// ...
});

test('two', async ({ page }) => {
// ...
});
});

标签

你可以通过提供额外的详细信息为组中的所有测试添加标签。请注意,每个标签都必须以 @ 符号开头。

🌐 You can tag all tests in a group by providing additional details. Note that each tag must start with @ symbol.

import { test, expect } from '@playwright/test';

test.describe('two tagged tests', {
tag: '@smoke',
}, () => {
test('one', async ({ page }) => {
// ...
});

test('two', async ({ page }) => {
// ...
});
});

了解有关tagging的更多信息。

🌐 Learn more about tagging.

注释

你可以通过提供附加详细信息来注释组中的所有测试。

🌐 You can annotate all tests in a group by providing additional details.

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 }) => {
// ...
});
});

了解有关 测试注释 的更多信息。

🌐 Learn more about test annotations.

参数


test.describe.configure

Added in: v1.10 test.test.describe.configure

配置外部作用域。可以在顶层或 describe 内执行。配置适用于整个作用域,无论是在测试声明之前还是之后运行。

🌐 Configures the enclosing scope. Can be executed either on the top level or inside a describe. Configuration applies to the entire scope, regardless of whether it run before or after the test declaration.

在这里了解更多关于执行模式的信息 here

🌐 Learn more about the execution modes here.

用法

  • 并行运行测试。

    // 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 }) => {});
  • 按顺序运行测试,从头重试。如果其中一个顺序测试失败,所有后续测试将被跳过。

    note

    不建议串行运行。通常最好使你的测试相互独立,这样它们可以独立运行。

    // 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 }) => {});
  • 并行运行多个描述,但每个描述内的测试按顺序进行。

    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 }) => {});
    });

参数

  • options Object (optional)
    • mode "default" | "parallel" | "serial" (optional)#

      执行模式。点击这里了解更多关于执行模式的信息。

    • retries number (optional) Added in: v1.28#

      每次测试的重试次数。

    • timeout number (optional) Added in: v1.28#

      每个测试的超时时间,以毫秒为单位。会覆盖 testProject.timeouttestConfig.timeout


test.describe.fixme

Added in: v1.25 test.test.describe.fixme

声明一个测试组,方式类似于 test.describe()。该组中的测试被标记为“fixme”,不会被执行。

🌐 Declares a test group similarly to test.describe(). Tests in this group are marked as "fixme" and will not be executed.

  • 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
});
});

你也可以省略标题。

🌐 You can also omit the title.

test.describe.fixme(() => {
// ...
});

参数


test.describe.only

Added in: v1.10 test.test.describe.only

声明一组重点测试。如果存在一些重点测试或测试套件,将运行它们全部,但不会运行其他测试。

🌐 Declares a focused group of tests. If there are some focused tests or suites, all of them will be run but nothing else.

  • 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
});

你也可以省略标题。

🌐 You can also omit the title.

test.describe.only(() => {
// ...
});

参数


test.describe.skip

Added in: v1.10 test.test.describe.skip

声明一个被跳过的测试组,类似于 test.describe()。被跳过组中的测试永远不会运行。

🌐 Declares a skipped test group, similarly to test.describe(). Tests in the skipped group are never run.

  • 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
});
});

你也可以省略标题。

🌐 You can also omit the title.

test.describe.skip(() => {
// ...
});

参数


test.extend

Added in: v1.10 test.test.extend

通过定义可在测试中使用的夹具和/或选项来扩展 test 对象。

🌐 Extends the test object by defining fixtures and/or options that can be used in the tests.

用法

首先定义一个夹具和/或一个选项。

🌐 First define a fixture and/or an option.

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();
},
});

然后在测试中使用夹具。

🌐 Then use the fixture in the test.

example.spec.ts
import { test } from './my-test';

test('test 1', async ({ todoPage }) => {
await todoPage.addToDo('my todo');
// ...
});

配置配置文件中的选项。

🌐 Configure the option in config file.

playwright.config.ts
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!' },
},
]
});

了解更多关于fixtures参数化测试的信息。

🌐 Learn more about fixtures and parametrizing tests.

参数

  • fixtures Object#

    一个包含夹具和/或选项的对象。了解更多关于夹具格式的信息。

返回


test.fail

Added in: v1.10 test.test.fail

将测试标记为“应该失败”。Playwright 会运行此测试并确保它实际上失败。这对于文档目的很有用,用于说明某些功能在修复之前是有问题的。

🌐 Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful for documentation purposes to acknowledge that some functionality is broken until it is fixed.

要声明一个“失败”测试:

🌐 To declare a "failing" test:

  • test.fail(title, body)
  • test.fail(title, details, body)

在运行时将测试标注为“失败”:

🌐 To annotate test as "failing" at runtime:

  • test.fail(condition, description)
  • test.fail(callback, description)
  • test.fail()

用法

你可以将测试声明为失败,以便 Playwright 确保它确实失败。

🌐 You can declare a test as failing, so that Playwright ensures it actually fails.

import { test, expect } from '@playwright/test';

test.fail('not yet ready', async ({ page }) => {
// ...
});

如果你的测试在某些配置下失败,但并非全部失败,你可以根据某些条件在测试主体中将测试标记为失败。我们建议在这种情况下传入一个 description 参数。

🌐 If your test fails in some configurations, but not all, you can mark the test as failing inside the test body based on some condition. We recommend passing a description argument in this case.

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() 组中的所有测试标记为“应该失败”。

🌐 You can mark all tests in a file or test.describe() group as "should fail" based on some condition with a single test.fail(callback, description) call.

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) 来声明一个失败的测试。

🌐 You can also call test.fail() without arguments inside the test body to always mark the test as failed. We recommend declaring a failing test with test.fail(title, body) instead.

import { test, expect } from '@playwright/test';

test('less readable', async ({ page }) => {
test.fail();
// ...
});

参数

  • title string (optional) Added in: v1.42#

    测试标题。

  • details Object (optional) Added in: v1.42#

    有关测试详情描述,请参见test()

  • body function(Fixtures, TestInfo) (optional) Added in: v1.42#

    测试主体,可接受一个或两个参数:包含测试夹具的对象和可选的 TestInfo

  • condition boolean (optional)#

    当条件为 true 时,测试被标记为“应该失败”。

  • callback function(Fixtures):boolean (optional)#

    一个根据测试夹具返回是否应标记为“应失败”的函数。当返回值为 true 时,测试或测试用例将被标记为“应失败”。

  • description string (optional)#

    将反映在测试报告中的可选描述。


test.fail.only

Added in: v1.49 test.test.fail.only

你可以使用 test.fail.only 来专注于预期会失败的特定测试。这在调试失败的测试或处理特定问题时尤其有用。

🌐 You can use test.fail.only to focus on a specific test that is expected to fail. This is particularly useful when debugging a failing test or working on a specific issue.

要声明一个聚焦的“失败”测试:

🌐 To declare a focused "failing" test:

  • test.fail.only(title, body)
  • test.fail.only(title, details, body)

用法

你可以声明一个重点失败测试,​​以便 Playwright 仅运行此测试并确保它确实失败。

🌐 You can declare a focused failing test, so that Playwright runs only this test and ensures it actually fails.

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.fixme

Added in: v1.10 test.test.fixme

将测试标记为“fixme”,表示有意修复它。Playwright 在 test.fixme() 调用之后不会运行该测试。

🌐 Mark a test as "fixme", with the intention to fix it. Playwright will not run the test past the test.fixme() call.

要声明一个“待修复”测试:

🌐 To declare a "fixme" test:

  • test.fixme(title, body)
  • test.fixme(title, details, body)

在运行时将测试标注为“待修复”:

🌐 To annotate test as "fixme" at runtime:

  • test.fixme(condition, description)
  • test.fixme(callback, description)
  • test.fixme()

用法

你可以声明一个测试已修复,而 Playwright 不会运行它。

🌐 You can declare a test as to be fixed, and Playwright will not run it.

import { test, expect } from '@playwright/test';

test.fixme('to be fixed', async ({ page }) => {
// ...
});

如果你的测试在某些配置下需要修复,但并非所有配置都需要修复,你可以根据某些条件在测试主体内将测试标记为“fixme”。我们建议在这种情况下传递一个 description 参数。Playwright 会运行测试,但会在 test.fixme 调用后立即中止。

🌐 If your test should be fixed in some configurations, but not all, you can mark the test as "fixme" inside the test body based on some condition. We recommend passing a description argument in this case. Playwright will run the test, but abort it immediately after the test.fixme call.

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() 组中的所有测试标记为“待修复”。

🌐 You can mark all tests in a file or test.describe() group as "fixme" based on some condition with a single test.fixme(callback, description) call.

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) 替代。

🌐 You can also call test.fixme() without arguments inside the test body to always mark the test as failed. We recommend using test.fixme(title, body) instead.

import { test, expect } from '@playwright/test';

test('less readable', async ({ page }) => {
test.fixme();
// ...
});

参数

  • title string (optional)#

    测试标题。

  • details Object (optional) Added in: v1.42#

    有关测试详情描述,请参见test()

  • body function(Fixtures, TestInfo) (optional)#

    测试主体,可接受一个或两个参数:包含测试夹具的对象和可选的 TestInfo

  • condition boolean (optional)#

    当条件为 true 时,测试被标记为“待修复”。

  • callback function(Fixtures):boolean (optional)#

    一个根据测试夹具返回是否标记为“fixme”的函数。当返回值为 true 时,测试或测试集会被标记为“fixme”.

  • description string (optional)#

    将反映在测试报告中的可选描述。


test.info

Added in: v1.10 test.test.info

返回有关当前运行测试的信息。此方法只能在测试执行期间调用,否则会抛出异常。

🌐 Returns information about the currently running test. This method can only be called during the test execution, otherwise it throws.

用法

test('example test', async ({ page }) => {
// ...
await test.info().attach('screenshot', {
body: await page.screenshot(),
contentType: 'image/png',
});
});

返回


test.only

Added in: v1.10 test.test.only

声明一个聚焦测试。如果存在一些聚焦测试或测试套件,将运行它们所有,但其他的不会运行。

🌐 Declares a focused test. If there are some focused tests or suites, all of them will be run but nothing else.

  • test.only(title, body)
  • test.only(title, details, body)

用法

test.only('focus this test', async ({ page }) => {
// Run only focused tests in the entire project.
});

参数


test.setTimeout

Added in: v1.10 test.test.setTimeout

更改测试的超时时间。零表示没有超时。了解有关各种超时的更多信息。

🌐 Changes the timeout for the test. Zero means no timeout. Learn more about various timeouts.

当前正在运行的测试的超时时间可以通过 testInfo.timeout 获取。

🌐 Timeout for the currently running test is available through testInfo.timeout.

用法

  • 更改测试超时。

    test('very slow test', async ({ page }) => {
    test.setTimeout(120000);
    // ...
    });
  • 正在更改来自慢速 beforeEach 钩子的超时。请注意,这会影响与 beforeEach 钩子共享的测试超时。

    test.beforeEach(async ({ page }, testInfo) => {
    // Extend timeout for all tests running this hook by 30 seconds.
    test.setTimeout(testInfo.timeout + 30000);
    });
  • 正在更改 beforeAllafterAll 钩子的超时。请注意,这会影响钩子的超时,而不是测试的超时。

    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 () => { /* ... */ });
    });

参数

  • timeout number#

    超时(以毫秒为单位)。


test.skip

Added in: v1.10 test.test.skip

跳过测试。Playwright 不会在 test.skip() 调用之后运行该测试。

🌐 Skip a test. Playwright will not run the test past the test.skip() call.

被跳过的测试不应该被执行。如果你打算修复测试,请使用 test.fixme()

🌐 Skipped tests are not supposed to be ever run. If you intend to fix the test, use test.fixme() instead.

要声明跳过的测试:

🌐 To declare a skipped test:

  • test.skip(title, body)
  • test.skip(title, details, body)

要在运行时跳过测试:

🌐 To skip a test at runtime:

  • test.skip(condition, description)
  • test.skip(callback, description)
  • test.skip()

用法

你可以声明跳过的测试,Playwright 将不会运行它。

🌐 You can declare a skipped test, and Playwright will not run it.

import { test, expect } from '@playwright/test';

test.skip('never run', async ({ page }) => {
// ...
});

如果你的测试在某些配置下应该被跳过,但不是全部,你可以根据某些条件在测试主体内部跳过该测试。在这种情况下,我们建议传递一个 description 参数。Playwright 会运行测试,但在 test.skip 调用之后立即中止。

🌐 If your test should be skipped in some configurations, but not all, you can skip the test inside the test body based on some condition. We recommend passing a description argument in this case. Playwright will run the test, but abort it immediately after the test.skip call.

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() 组中的所有测试。

🌐 You can skip all tests in a file or test.describe() group based on some condition with a single test.skip(callback, description) call.

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)

🌐 You can also call test.skip() without arguments inside the test body to always skip the test. However, we recommend using test.skip(title, body) instead.

import { test, expect } from '@playwright/test';

test('less readable', async ({ page }) => {
test.skip();
// ...
});

参数

  • title string (optional)#

    测试标题。

  • details Object (optional) Added in: v1.42#

    有关测试详情描述,请参见test()

  • body function(Fixtures, TestInfo) (optional)#

    测试主体,可接受一个或两个参数:包含测试夹具的对象和可选的 TestInfo

  • condition boolean (optional)#

    当条件为 true 时,测试被标记为“跳过”。

  • callback function(Fixtures):boolean (optional)#

    一个根据测试夹具返回是否标记为“跳过”的函数。当返回值为 true 时,测试或测试集会被标记为“跳过”.

  • description string (optional)#

    将反映在测试报告中的可选描述。


test.slow

Added in: v1.10 test.test.slow

将测试标记为“慢速”。慢速测试将获得默认超时的三倍时间。

🌐 Marks a test as "slow". Slow test will be given triple the default timeout.

请注意,test.slow() 不能在 beforeAllafterAll 钩子中使用。请改用 test.setTimeout()

🌐 Note that test.slow() cannot be used in a beforeAll or afterAll hook. Use test.setTimeout() instead.

  • test.slow()
  • test.slow(condition, description)
  • test.slow(callback, description)

用法

你可以在测试主体内调用 test.slow() 来将测试标记为慢速。

🌐 You can mark a test as slow by calling test.slow() inside the test body.

import { test, expect } from '@playwright/test';

test('slow test', async ({ page }) => {
test.slow();
// ...
});

如果你的测试在某些配置下运行缓慢,但并非所有配置都这样,你可以根据条件将其标记为慢。我们建议在这种情况下传递一个 description 参数。

🌐 If your test is slow in some configurations, but not all, you can mark it as slow based on a condition. We recommend passing a description argument in this case.

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() 组中的所有测试标记为“慢”。

🌐 You can mark all tests in a file or test.describe() group as "slow" based on some condition by passing a callback.

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 }) => {
// ...
});

参数

  • condition boolean (optional)#

    当条件为 true 时,测试被标记为“慢”。

  • callback function(Fixtures):boolean (optional)#

    一个函数,根据测试夹具返回是否标记为“慢”。当返回值为 true 时,测试或测试组会被标记为“慢”。

  • description string (optional)#

    将反映在测试报告中的可选描述。


test.step

Added in: v1.10 test.test.step

声明报告中显示的测试步骤。

🌐 Declares a test step that is shown in the report.

用法

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 () => {
// ...
});
});
});

参数

  • title string#

    步骤名称。

  • body function(TestStepInfo):Promise<Object>#

    步体。

  • options Object (optional)

    • box boolean (optional) Added in: v1.39#

      是否在报告中给步骤加框。默认值为 false。当步骤被加框时,步骤内部抛出的错误将指向步骤调用位置。详情见下文。

    • location Location (optional) Added in: v1.48#

      指定在测试报告和跟踪查看器中显示步骤的自定义位置。默认情况下,会显示test.step()调用的位置。

    • timeout number (optional) Added in: v1.50#

      允许步骤完成的最长时间,单位为毫秒。如果步骤未能在指定的超时时间内完成,test.step() 方法将抛出 TimeoutError。默认值为 0(无超时)。

返回

详情

该方法返回步骤回调返回的值。

🌐 The method returns the value returned by the step callback.

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 方法装饰器将一个方法变成一个步骤。每次调用被装饰的方法都会在报告中显示为一个步骤。

🌐 You can use TypeScript method decorators to turn a method into a step. Each call to the decorated method will show up as a step in the report.

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

拳击

当某个步骤中的某个操作失败时,你通常会看到错误指向具体失败的操作。例如,考虑以下登录步骤:

🌐 When something inside a step fails, you would usually see the error pointing to the exact action that failed. For example, consider the following login step:

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 | });

如上所述,测试可能因误差指向步骤内部而失败。如果你希望错误显示“登录”步骤而非内部内容,请使用“box”选项。方框步内的错误指向步调点。

🌐 As we see above, the test may fail with an error pointing inside the step. If you would like the error to highlight the "login" step instead of its internals, use the box option. An error inside a boxed step points to the step call site.

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 装饰器,类似于上面的常规步骤装饰器:

🌐 You can also create a TypeScript decorator for a boxed step, similar to a regular step decorator above:

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

Added in: v1.50 test.test.step.skip

将测试步骤标记为“跳过”,以暂时禁用其执行,这对于当前失败且计划近期修复的步骤很有用。Playwright 不会执行该步骤。另请参见 testStepInfo.skip()

🌐 Mark a test step as "skip" to temporarily disable its execution, useful for steps that are currently failing and planned for a near-term fix. Playwright will not run the step. See also testStepInfo.skip().

我们建议改用 testStepInfo.skip()

🌐 We recommend testStepInfo.skip() instead.

用法

你可以声明跳过的步骤,Playwright 将不会运行它。

🌐 You can declare a skipped step, and Playwright will not run it.

import { test, expect } from '@playwright/test';

test('my test', async ({ page }) => {
// ...
await test.step.skip('not yet ready', async () => {
// ...
});
});

参数

  • title string#

    步骤名称。

  • body function():Promise<Object>#

    步体。

  • options Object (optional)

    • box boolean (optional)#

      是否在报告中给步骤加框。默认值为 false。当步骤被加框时,步骤内部抛出的错误将指向步骤调用位置。详情见下文。

    • location Location (optional)#

      指定在测试报告和跟踪查看器中显示步骤的自定义位置。默认情况下,会显示test.step()调用的位置。

    • timeout number (optional)#

      步骤完成的最大时间(毫秒)。默认为“0”(无超时)。

返回


test.use

Added in: v1.10 test.test.use

指定在单个测试文件或 test.describe() 组中使用的选项或夹具。最常用于设置选项,例如设置 locale 以配置 context 夹具。

🌐 Specifies options or fixtures to use in a single test file or a test.describe() group. Most useful to set an option, for example set locale to configure context fixture.

用法

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
});

参数

详情

test.use 可以在全局作用域或 test.describe 内部调用。在 beforeEachbeforeAll 中调用它是错误的。

还可以通过提供函数来覆盖夹具。

🌐 It is also possible to override a fixture by providing a function.

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
});

属性

🌐 Properties

test.expect

Added in: v1.10 test.test.expect

expect 函数可以用于创建测试断言。了解更多关于 测试断言 的信息。

用法

test('example', async ({ page }) => {
await test.expect(page).toHaveTitle('Title');
});

类型


已弃用

🌐 Deprecated

test.describe.parallel

Added in: v1.10 test.test.describe.parallel
Discouraged

请参阅 test.describe.configure() 以了解配置执行模式的首选方式。

🌐 See test.describe.configure() for the preferred way of configuring the execution mode.

声明一组可以并行运行的测试。默认情况下,单个测试文件中的测试会一个接一个地执行,但使用 test.describe.parallel() 可以让它们并行执行。

🌐 Declares a group of tests that could be run in parallel. By default, tests in a single test file run one after another, but using test.describe.parallel() allows them to run in 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 }) => {});
});

请注意,平行测试在独立的进程中执行,无法共享任何状态或全局变量。每个平行测试都会执行所有相关的钩子。

🌐 Note that parallel tests are executed in separate processes and cannot share any state or global variables. Each of the parallel tests executes all relevant hooks.

你也可以省略标题。

🌐 You can also omit the title.

test.describe.parallel(() => {
// ...
});

参数


test.describe.parallel.only

Added in: v1.10 test.test.describe.parallel.only
Discouraged

请参阅 test.describe.configure() 以了解配置执行模式的首选方式。

🌐 See test.describe.configure() for the preferred way of configuring the execution mode.

声明一组可以并行运行的集中测试。这类似于 test.describe.parallel(),但它专注于该组测试。如果有一些集中测试或套件,它们都会被运行,而其他的不会被运行。

🌐 Declares a focused group of tests that could be run in parallel. This is similar to test.describe.parallel(), but focuses the group. If there are some focused tests or suites, all of them will be run but nothing else.

  • 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 }) => {});
});

你也可以省略标题。

🌐 You can also omit the title.

test.describe.parallel.only(() => {
// ...
});

参数


test.describe.serial

Added in: v1.10 test.test.describe.serial
Discouraged

请参阅 test.describe.configure() 以了解配置执行模式的首选方式。

🌐 See test.describe.configure() for the preferred way of configuring the execution mode.

声明一组应始终按顺序运行的测试。如果其中一个测试失败,则所有后续测试将被跳过。组中的所有测试将一起重试。

🌐 Declares a group of tests that should always be run serially. If one of the tests fails, all subsequent tests are skipped. All tests in a group are retried together.

note

不推荐使用串行。通常最好使你的测试相互独立,这样它们可以独立运行。

🌐 Using serial is not recommended. It is usually better to make your tests isolated, so they can be run independently.

  • 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 }) => {});
});

你也可以省略标题。

🌐 You can also omit the title.

test.describe.serial(() => {
// ...
});

参数


test.describe.serial.only

Added in: v1.10 test.test.describe.serial.only
Discouraged

请参阅 test.describe.configure() 以了解配置执行模式的首选方式。

🌐 See test.describe.configure() for the preferred way of configuring the execution mode.

声明一组应始终串行运行的集中测试。如果其中一个测试失败,则所有后续测试将被跳过。组中的所有测试会一起重试。如果有一些集中测试或测试套件,它们将全部运行,但不会运行其他任何测试。

🌐 Declares a focused group of tests that should always be run serially. If one of the tests fails, all subsequent tests are skipped. All tests in a group are retried together. If there are some focused tests or suites, all of them will be run but nothing else.

note

不推荐使用串行。通常最好使你的测试相互独立,这样它们可以独立运行。

🌐 Using serial is not recommended. It is usually better to make your tests isolated, so they can be run independently.

  • 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 }) => {
});
});

你也可以省略标题。

🌐 You can also omit the title.

test.describe.serial.only(() => {
// ...
});

参数