Skip to main content

Playwright Test

Playwright Test 提供了一个 test 函数来声明测试,以及 expect 函数 来编写断言。

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

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

test(title, testFunction)

Added in: v1.10

声明一个测试。

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

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

test.afterAll(hookFunction)

Added in: v1.10

声明一个 afterAll 钩子,该钩子在每个 worker 的所有测试之后执行一次。当在测试文件的范围内调用时,在文件中的所有测试之后运行。当在 test.describe(title, callback) 组内调用时,在组内的所有测试之后运行。如果添加了多个 afterAll 钩子,它们将按照注册的顺序运行。

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

test.afterEach(hookFunction)

Added in: v1.10

声明一个 afterEach 钩子,该钩子在每个测试之后执行。当在测试文件的范围内调用时,在文件中的每个测试之后运行。当在 test.describe(title, callback) 组内调用时,在组内的每个测试之后运行。如果添加了多个 afterEach 钩子,它们将按照注册的顺序运行。

您可以访问与测试函数本身相同的所有 Fixtures,以及提供大量有用信息的 TestInfo 对象。例如,您可以检查测试是成功还是失败。

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

test.afterEach(async ({ page }, testInfo) => {
console.log(`Finished ${testInfo.title} with status ${testInfo.status}`);

if (testInfo.status !== testInfo.expectedStatus)
console.log(`Did not run as expected, ended up at ${page.url()}`);
});

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

test.beforeAll(hookFunction)

Added in: v1.10

声明一个 beforeAll 钩子,该钩子在每个 worker 进程的所有测试之前执行一次。当在测试文件的范围内调用时,在文件中的所有测试之前运行。当在 test.describe(title, callback) 组内调用时,在组内的所有测试之前运行。如果添加了多个 beforeAll 钩子,它们将按照注册的顺序运行。

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

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

您可以使用 test.afterAll(hookFunction) 来拆卸在 beforeAll 中设置的任何资源。

test.beforeEach(hookFunction)

Added in: v1.10

声明一个 beforeEach 钩子,该钩子在每个测试之前执行。当在测试文件的范围内调用时,在文件中的每个测试之前运行。当在 test.describe(title, callback) 组内调用时,在组内的每个测试之前运行。如果添加了多个 beforeEach 钩子,它们将按照注册的顺序运行。

您可以访问与测试函数本身相同的所有 Fixtures,以及提供大量有用信息的 TestInfo 对象。例如,您可以检查测试是成功还是失败。

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

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

test('my test', async ({ page }) => {
expect(page.url()).toBe('https://my.start.url/');
});

您可以使用 test.afterEach(hookFunction) 来拆卸在 beforeEach 中设置的任何资源。

test.describe(title, callback)

Added in: v1.10

声明一组测试。

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

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

test.describe(callback)

Added in: v1.24

声明一个匿名测试组。这对于使用 test.use(options) 为一组测试提供公共选项非常方便。

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

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

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

test.describe.configure([options])

Added in: v1.10
  • options? <Object>
    • mode? <"parallel"|"serial">#
  • returns: <void>#

设置封闭范围的执行模式。可以在顶层或 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 }) => {});

按顺序运行测试:

// Annotate tests as inter-dependent.
test.describe.configure({ mode: 'serial' });
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {});

test.describe.fixme(title, callback)

Added in: v1.25

声明一个测试组,类似于 test.describe(title, callback)。该组中的测试被标记为 "fixme",并且不会执行。

test.describe.fixme('broken tests', () => {
test('example', async ({ page }) => {
// This test will not run
});
});

test.describe.only(title, callback)

Added in: v1.10

声明一个聚焦的测试组。如果有一些聚焦的测试或套件,则只会运行它们,而不会运行其他任何内容。

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.parallel(title, callback)

Added in: v1.10

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

note

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

test.describe.parallel('group', () => {
test('runs in parallel 1', async ({ page }) => {});
test('runs in parallel 2', async ({ page }) => {});
});

请注意,并行测试在单独的进程中执行,不能共享任何状态或全局变量。每个并行测试都执行所有相关的钩子。

test.describe.parallel.only(title, callback)

Added in: v1.10

声明一个可以并行运行的聚焦测试组。这类似于 test.describe.parallel(title, callback),但聚焦于该组。如果有一些聚焦的测试或套件,则只会运行它们,而不会运行其他任何内容。

test.describe.serial(title, callback)

Added in: v1.10

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

note

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

note

不建议使用 serial。通常最好使您的测试相互隔离,以便它们可以独立运行。

test.describe.serial('group', () => {
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {});
});

test.describe.serial.only(title, callback)

Added in: v1.10

声明一个应始终按顺序运行的聚焦测试组。如果其中一个测试失败,则跳过所有后续测试。组中的所有测试将一起重试。如果有一些聚焦的测试或套件,则只会运行它们,而不会运行其他任何内容。

note

不建议使用 serial。通常最好使您的测试相互隔离,以便它们可以独立运行。

test.describe.serial.only('group', () => {
test('runs first', async ({ page }) => {
});
test('runs second', async ({ page }) => {
});
});

test.describe.skip(title, callback)

Added in: v1.10

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

test.describe.skip('skipped group', () => {
test('example', async ({ page }) => {
// This test will not run
});
});

test.extend(fixtures)

Added in: v1.10

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

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

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

然后在测试中使用该 fixture。

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

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

在配置文件中配置该选项。

// playwright.config.ts
import type { PlaywrightTestConfig } from '@playwright/test';
import { Options } from './my-test';

const config: PlaywrightTestConfig<Options> = {
projects: [
{
name: 'shopping',
use: { defaultItem: 'Buy milk' },
},
{
name: 'wellbeing',
use: { defaultItem: 'Exercise!' },
},
]
};
export default config;

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

test.fail()

Added in: v1.10

无条件地将测试标记为 "should fail"(应该失败)。Playwright Test 运行此测试并确保它实际上是失败的。这对于文档目的很有用,以确认某些功能在修复之前已损坏。

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

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

test.fail(condition[, description])

Added in: v1.10
  • condition <boolean> 当条件为 true 时,测试被标记为 "should fail"。#
  • description? <string> 可选描述,将反映在测试报告中。#
  • returns: <void>#

有条件地将测试标记为 "should fail",并带有可选描述。

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])

Added in: v1.10
  • callback <function(Fixtures):boolean> 一个函数,根据测试 fixtures 返回是否标记为 "should fail"。当返回值为 true 时,测试或测试组被标记为 "should fail"。#
  • description? <string> 可选描述,将反映在测试报告中。#
  • returns: <void>#

有条件地将文件或 test.describe(title, callback) 组中的所有测试标记为 "should fail"。

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

test.fail(({ browserName }) => browserName === 'webkit');

test('fail in WebKit 1', async ({ page }) => {
// ...
});
test('fail in WebKit 2', async ({ page }) => {
// ...
});

test.fixme(title, testFunction)

Added in: v1.10

声明一个待修复的测试,类似于 test(title, testFunction)。此测试将不会运行。

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

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

test.fixme()

Added in: v1.10

将测试标记为 "fixme",意图修复它。当您调用 test.fixme() 时,测试立即中止。

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

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

将文件或 test.describe(title, callback) 组中的所有测试标记为 "fixme"。

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

test.fixme();

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

test.fixme(condition[, description])

Added in: v1.10
  • condition <boolean> 当条件为 true 时,测试被标记为 "fixme"。#
  • description? <string> 可选描述,将反映在测试报告中。#
  • returns: <void>#

有条件地将测试标记为 "fixme",并带有可选描述。

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

test('broken in WebKit', async ({ page, browserName }) => {
test.fixme(browserName === 'webkit', 'This feature is not implemented on Mac yet');
// ...
});

test.fixme(callback[, description])

Added in: v1.10
  • callback <function(Fixtures):boolean> 一个函数,根据测试 fixtures 返回是否标记为 "fixme"。当返回值为 true 时,测试或测试组被标记为 "fixme"。#
  • description? <string> 可选描述,将反映在测试报告中。#
  • returns: <void>#

有条件地将文件或 test.describe(title, callback) 组中的所有测试标记为 "fixme"。

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

test.fixme(({ browserName }) => browserName === 'webkit');

test('broken in WebKit 1', async ({ page }) => {
// ...
});
test('broken in WebKit 2', async ({ page }) => {
// ...
});

test.info()

Added in: v1.10

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

test.only(title, testFunction)

Added in: v1.10

声明一个聚焦的测试。如果有一些聚焦的测试或套件,则只会运行它们,而不会运行其他任何内容。

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

test.setTimeout(timeout)

Added in: v1.10
  • timeout <number> 超时时间(毫秒)。#
  • returns: <void>#

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

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

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

从缓慢的 beforeEachafterEach 钩子更改超时。请注意,这会影响与 beforeEach/afterEach 钩子共享的测试超时。

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

test.beforeEach(async ({ page }, testInfo) => {
// Extend timeout for all tests running this hook by 30 seconds.
test.setTimeout(testInfo.timeout + 30000);
});

更改 beforeAllafterAll 钩子的超时。请注意,这会影响钩子的超时,而不是测试超时。

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

test.beforeAll(async () => {
// Set timeout for this hook.
test.setTimeout(60000);
});

更改 test.describe(title, callback) 组中所有测试的超时。

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

test.describe('group', () => {
// Applies to all tests in this group.
test.setTimeout(60000);

test('test one', async () => { /* ... */ });
test('test two', async () => { /* ... */ });
test('test three', async () => { /* ... */ });
});

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

test.skip(title, testFunction)

Added in: v1.10

声明一个跳过的测试,类似于 test(title, testFunction)。跳过的测试永远不会运行。

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

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

test.skip()

Added in: v1.10

无条件地跳过测试。当您调用 test.skip() 时,测试立即中止。

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

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

无条件地跳过文件或 test.describe(title, callback) 组中的所有测试:

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

test.skip();

test('skipped test 1', async ({ page }) => {
// ...
});
test('skipped test 2', async ({ page }) => {
// ...
});

test.skip(condition[, description])

Added in: v1.10
  • condition <boolean> 跳过条件。当条件为 true 时,测试被跳过。#
  • description? <void|string> 可选描述,将反映在测试报告中。#
  • returns: <void>#

有条件地跳过测试,并带有可选描述。

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

test('skip in WebKit', async ({ page, browserName }) => {
test.skip(browserName === 'webkit', 'This feature is not implemented for Mac');
// ...
});

test.beforeEach(hookFunction) 钩子跳过:

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

test.beforeEach(async ({ page }) => {
test.skip(process.env.APP_VERSION === 'v1', 'There are no settings in v1');
await page.goto('/settings');
});

test.skip(callback[, description])

Added in: v1.10
  • callback <function(Fixtures):boolean> 一个函数,根据测试 fixtures 返回是否跳过。当返回值为 true 时,测试或测试组被跳过。#
  • description? <string> 可选描述,将反映在测试报告中。#
  • returns: <void>#

有条件地跳过文件或 test.describe(title, callback) 组中的所有测试。

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

test.skip(({ browserName }) => browserName === 'webkit');

test('skip in WebKit 1', async ({ page }) => {
// ...
});
test('skip in WebKit 2', async ({ page }) => {
// ...
});

test.slow()

Added in: v1.10

无条件地将测试标记为 "slow"(慢速)。慢速测试将获得三倍的默认超时时间。

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

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

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

test.slow(condition[, description])

Added in: v1.10
  • condition <boolean> 当条件为 true 时,测试被标记为 "slow"。#
  • description? <string> 可选描述,将反映在测试报告中。#
  • returns: <void>#

有条件地将测试标记为 "slow",并带有可选描述。慢速测试将获得三倍的默认超时时间。

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

test('slow in WebKit', async ({ page, browserName }) => {
test.slow(browserName === 'webkit', 'This feature is slow on Mac');
// ...
});

test.slow(callback[, description])

Added in: v1.10
  • callback <function(Fixtures):boolean> 一个函数,根据测试 fixtures 返回是否标记为 "slow"。当返回值为 true 时,测试或测试组被标记为 "slow"。#
  • description? <string> 可选描述,将反映在测试报告中。#
  • returns: <void>#

有条件地将文件或 test.describe(title, callback) 组中的所有测试标记为 "slow"。慢速测试将获得三倍的默认超时时间。

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

test.slow(({ browserName }) => browserName === 'webkit');

test('slow in WebKit 1', async ({ page }) => {
// ...
});
test('fail in WebKit 2', async ({ page }) => {
// ...
});

test.step(title, body)

Added in: v1.10

声明一个测试步骤。

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

test('test', async ({ page }) => {
await test.step('Log in', async () => {
// ...
});
});

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

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

test('test', async ({ page }) => {
const user = await test.step('Log in', async () => {
// ...
return 'john';
});
expect(user).toBe('john');
});

test.use(options)

Added in: v1.10

指定在单个测试文件或 test.describe(title, callback) 组中使用的选项或 fixtures。最常用于设置选项,例如设置 locale 以配置 context fixture。test.use 可以在全局范围内或在 test.describe 内部调用,在 beforeEachbeforeAll 中调用它是错误的。

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

也可以通过提供函数来覆盖 fixture。

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

Added in: v1.10

expect 函数可用于创建测试断言。阅读 expect 库文档 了解更多详情。