Skip to main content

全局设置和拆卸

介绍

Introduction

有两种方法可以配置全局设置和拆卸:使用全局设置文件并将其设置在 globalSetup 下的配置中或使用 项目依赖。通过项目依赖,你可以定义一个在所有其他项目之前运行的项目。这是配置全局设置的推荐方法,因为项目依赖你的 HTML 报告将显示全局设置,跟踪查看器将记录设置的跟踪,并且可以使用夹具。

There are two ways to configure global setup and teardown: using a global setup file and setting it in the config under globalSetup or using project dependencies. With project dependencies, you define a project that runs before all other projects. This is the recommended way to configure global setup as with Project dependencies your HTML report will show the global setup, trace viewer will record a trace of the setup and fixtures can be used.

选项 1:项目依赖

Option 1: Project Dependencies

项目依赖 是在另一个项目中的测试运行之前需要运行的项目列表。它们对于配置全局设置操作非常有用,以便一个项目首先依赖于此运行。使用依赖允许全局设置生成跟踪和其他工件。

Project dependencies are a list of projects that need to run before the tests in another project run. They can be useful for configuring the global setup actions so that one project depends on this running first. Using dependencies allows global setup to produce traces and other artifacts.

设置

Setup

首先我们添加一个名为 'setup' 的新项目。然后我们给它一个 testProject.testMatch 属性以匹配名为 global.setup.ts 的文件:

First we add a new project with the name 'setup'. We then give it a testProject.testMatch property in order to match the file called global.setup.ts:

playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './tests',
// ...
projects: [
{
name: 'setup',
testMatch: /global.setup\.ts/,
},
// {
// other project
// }
]
});

然后,我们将 testProject.dependencies 属性添加到依赖于安装项目的项目中,并将我们在上一步中定义的依赖目的名称传递到数组中:

Then we add the testProject.dependencies property to our projects that depend on the setup project and pass into the array the name of of our dependency project, which we defined in the previous step:

playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
testDir: './tests',
// ...
projects: [
{
name: 'setup',
testMatch: /global\.setup\.ts/,
},
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
dependencies: ['setup'],
},
]
});

设置示例

Setup Example

此示例将向你展示如何使用项目依赖来创建登录应用并将状态保存在存储状态中的全局设置。如果你想要运行需要登录状态的多个测试并且想要避免每个测试都登录,这非常有用。

This example will show you how to use project dependencies to create a global setup that logins into an application and saves the state in storage state. This is useful if you want to run multiple tests that require a sign sign-in state and you want to avoid login for each test.

安装项目会将存储状态写入 playwright.config 旁边的 'playwright/.auth/user.json' 文件中。通过导出 STORAGE_STATE 的 const,我们可以使用 StorageState 方法轻松地在项目之间共享存储文件的位置。这将存储状态应用于浏览器上下文及其 cookie 和本地存储快照。

The setup project will write the storage state into an 'playwright/.auth/user.json' file next to your playwright.config. By exporting a const of STORAGE_STATE we can then easily share the location of the storage file between projects with the StorageState method. This applies the storage state on the browser context with its cookies and a local storage snapshot.

在此示例中,'登录 chromium' 项目依赖于安装项目,而 '注销 chromium' 项目不依赖于安装项目,并且不使用 storageState 选项。

In this example the 'logged in chromium' project depends on the setup project whereas the 'logged out chromium' project does not depend on the setup project, and does not use the storageState option.

playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export const STORAGE_STATE = path.join(__dirname, 'playwright/.auth/user.json');

export default defineConfig({
testDir: './tests',
// ...
use: {
baseURL: 'http://localhost:3000/',
},
projects: [
{
name: 'setup',
testMatch: /global\.setup\.ts/,
},
{
name: 'logged in chromium',
testMatch: '**/*.loggedin.spec.ts',
dependencies: ['setup'],
use: {
...devices['Desktop Chrome'],
storageState: STORAGE_STATE,
},
},
{
name: 'logged out chromium',
use: { ...devices['Desktop Chrome'] },
testIgnore: ['**/*loggedin.spec.ts']
},
],
});

然后,我们创建一个设置测试,存储在项目的根级别,该测试登录到应用并在执行登录操作后使用存储状态填充上下文。通过执行此操作,你只需登录一次,凭据将存储在 STORAGE_STATE 文件中,这意味着你无需为每次测试再次登录。首先从 Playwright 配置文件导入 STORAGE_STATE,然后使用它作为将存储状态保存到页面上下文的路径。

We then create a setup test, stored at root level of your project, that logs in to an application and populates the context with the storage state after the login actions have been performed. By doing this you only have to log in once and the credentials will be stored in the STORAGE_STATE file, meaning you don't need to log in again for every test. Start by importing the STORAGE_STATE from the Playwright config file and then use this as the path to save your storage state to the page's context.

tests/global.setup.ts
import { test as setup, expect } from '@playwright/test';
import { STORAGE_STATE } from '../playwright.config';

setup('do login', async ({ page }) => {
await page.goto('/');
await page.getByLabel('User Name').fill('user');
await page.getByLabel('Password').fill('password');
await page.getByText('Sign in').click();

// Wait until the page actually signs in.
await expect(page.getByText('Hello, user!')).toBeVisible();

await page.context().storageState({ path: STORAGE_STATE });
});
tests/menu.loggedin.spec.ts
import { test, expect } from '@playwright/test';

test.beforeEach(async ({ page }) => {
await page.goto('/');
});

test('menu', async ({ page }) => {
// You are signed in!
});

有关更详细的示例,请查看我们的博客文章:Playwright 中更好的全局设置重用带有项目依赖的登录 或查看 v1.31 发布视频 查看演示。

For a more detailed example check out our blog post: A better global setup in Playwright reusing login with project dependencies or check the v1.31 release video to see the demo.

拆除

Teardown

你可以通过向安装项目添加 testProject.teardown 属性来拆卸你的安装。这将在所有依赖目运行后运行。

You can teardown your setup by adding a testProject.teardown property to your setup project. This will run after all dependent projects have run.

首先,我们将一个新项目添加到项目数组中,并为其命名,例如 '清理数据库'。然后我们给它一个 testProject.testMatch 属性以匹配名为 global.teardown.ts 的文件:

First we add a new project into the projects array and give it a name such as 'cleanup db'. We then give it a testProject.testMatch property in order to match the file called global.teardown.ts:

playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './tests',
// ...
projects: [
// {
// setup project
// },
{
name: 'cleanup db',
testMatch: /global\.teardown\.ts/,
},
// {
// other project
// }
]
});

然后,我们将 testProject.teardown 属性添加到我们的安装项目中,名称为 '清理数据库',这是我们在上一步中为拆卸项目指定的名称:

Then we add the testProject.teardown property to our setup project with the name 'cleanup db' which is the name we gave to our teardown project in the previous step:

playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './tests',
// ...
projects: [
{
name: 'setup db',
testMatch: /global\.setup\.ts/,
teardown: 'cleanup db',
},
{
name: 'cleanup db',
testMatch: /global\.teardown\.ts/,
},
// {
// other project
// }
]
});

拆解示例

Teardown Example

首先在项目的测试目录中创建一个 global.setup.ts 文件。这将用于在所有测试运行之前向数据库添加一些数据。

Start by creating a global.setup.ts file in the tests directory of your project. This will be used to seed the database with some data before all tests have run.

tests/global.setup.ts
// seed the database with some data

然后在项目的 tests 目录中创建一个 global.teardown.ts 文件。这将用于在所有测试运行后从数据库中删除数据。

Then create a global.teardown.ts file in the tests directory of your project. This will be used to delete the data from the database after all tests have run.

tests/global.teardown.ts
// delete the data from the database

在 Playwright 配置文件中:

In the Playwright config file:

  • 将项目添加到项目数组中并为其命名,例如 '设置数据库'。为其指定 testProject.testMatch 属性以匹配名为 global.setup.ts 的文件。

    Add a project into the projects array and give it a name such as 'setup db'. Give it a testProject.testMatch property in order to match the file called global.setup.ts.

  • 创建另一个项目并为其命名,例如 '清理数据库'。为其指定 testProject.testMatch 属性以匹配名为 global.teardown.ts 的文件。

    Create another project and give it a name such as 'cleanup db'. Give it a testProject.testMatch property in order to match the file called global.teardown.ts.

  • testProject.teardown 属性添加到我们的安装项目中,名称为 '清理数据库',这是上一步中为我们的拆卸项目指定的名称。最后将 'chromium' 项目与 testProject.dependencies 添加到 '设置数据库' 项目上。

    Add the testProject.teardown property to our setup project with the name 'cleanup db' which is the name given to our teardown project in the previous step. Finally add the 'chromium' project with the testProject.dependencies on the 'setup db' project.

playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './tests',
// ...
projects: [
{
name: 'setup db',
testMatch: /global\.setup\.ts/,
teardown: 'cleanup db',
},
{
name: 'cleanup db',
testMatch: /global\.teardown\.ts/,
},
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
dependencies: ['setup db'],
},
]
});

选项 2:配置 globalSetup 和 globalTeardown

Option 2: Configure globalSetup and globalTeardown

你可以在运行所有测试之前使用 配置文件 中的 globalSetup 选项进行一次设置。全局设置文件必须导出一个采用配置对象的函数。该函数将在所有测试之前运行一次。

You can use the globalSetup option in the configuration file to set something up once before running all tests. The global setup file must export a single function that takes a config object. This function will be run once before all the tests.

同样,在所有测试之后使用 globalTeardown 运行一次。或者,让 globalSetup 返回一个将用作全局拆卸的函数。你可以使用环境变量将端口号、身份验证令牌等数据从全局设置传递到测试。

Similarly, use globalTeardown to run something once after all the tests. Alternatively, let globalSetup return a function that will be used as a global teardown. You can pass data such as port number, authentication tokens, etc. from your global setup to your tests using environment variables.

注意

使用 globalSetupglobalTeardown 不会产生痕迹或伪影。如果你想产生痕迹和工件,请使用 项目依赖

Using globalSetup and globalTeardown will not produce traces or artifacts. If you want to produce traces and artifacts, use project dependencies.

playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
globalSetup: require.resolve('./global-setup'),
globalTeardown: require.resolve('./global-teardown'),
});

示例

Example

以下是一个全局设置示例,该示例仅进行一次身份验证并在测试中重用身份验证状态。它使用配置文件中的 baseURLstorageState 选项。

Here is a global setup example that authenticates once and reuses authentication state in tests. It uses the baseURL and storageState options from the configuration file.

global-setup.ts
import { chromium, type FullConfig } from '@playwright/test';

async function globalSetup(config: FullConfig) {
const { baseURL, storageState } = config.projects[0].use;
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(baseURL!);
await page.getByLabel('User Name').fill('user');
await page.getByLabel('Password').fill('password');
await page.getByText('Sign in').click();
await page.context().storageState({ path: storageState as string });
await browser.close();
}

export default globalSetup;

在配置文件中指定 globalSetupbaseURLstorageState

Specify globalSetup, baseURL and storageState in the configuration file.

playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
globalSetup: require.resolve('./global-setup'),
use: {
baseURL: 'http://localhost:3000/',
storageState: 'state.json',
},
});

测试开始时已经经过身份验证,因为我们指定了由全局设置填充的 storageState

Tests start already authenticated because we specify storageState that was populated by global setup.

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

test('test', async ({ page }) => {
await page.goto('/');
// You are signed in!
});

你可以通过 process.env 将任意数据设置为环境变量,从而使全局设置文件中的任意数据在测试中可用。

You can make arbitrary data available in your tests from your global setup file by setting them as environment variables via process.env.

global-setup.ts
import type { FullConfig } from '@playwright/test';

async function globalSetup(config: FullConfig) {
process.env.FOO = 'some data';
// Or a more complicated data structure as JSON:
process.env.BAR = JSON.stringify({ some: 'data' });
}

export default globalSetup;

测试可以访问全局设置中设置的 process.env 属性。

Tests have access to the process.env properties set in the global setup.

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

test('test', async ({ page }) => {
// environment variables which are set in globalSetup are only available inside test().
const { FOO, BAR } = process.env;

// FOO and BAR properties are populated.
expect(FOO).toEqual('some data');

const complexData = JSON.parse(BAR);
expect(BAR).toEqual({ some: 'data' });
});

捕获全局设置期间的故障痕迹

Capturing trace of failures during global setup

在某些情况下,捕获全局设置期间遇到的故障的踪迹可能很有用。为此,你必须在设置中执行 开始追踪,并且必须确保在发生错误时执行 停止追踪,然后才会引发该错误。这可以通过将你的设置封装在 try...catch 块中来实现。下面是扩展全局设置示例以捕获跟踪的示例。

In some instances, it may be useful to capture a trace of failures encountered during the global setup. In order to do this, you must start tracing in your setup, and you must ensure that you stop tracing if an error occurs before that error is thrown. This can be achieved by wrapping your setup in a try...catch block. Here is an example that expands the global setup example to capture a trace.

global-setup.ts
import { chromium, type FullConfig } from '@playwright/test';

async function globalSetup(config: FullConfig) {
const { baseURL, storageState } = config.projects[0].use;
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
try {
await context.tracing.start({ screenshots: true, snapshots: true });
await page.goto(baseURL!);
await page.getByLabel('User Name').fill('user');
await page.getByLabel('Password').fill('password');
await page.getByText('Sign in').click();
await context.storageState({ path: storageState as string });
await context.tracing.stop({
path: './test-results/setup-trace.zip',
});
await browser.close();
} catch (error) {
await context.tracing.stop({
path: './test-results/failed-setup-trace.zip',
});
await browser.close();
throw error;
}
}

export default globalSetup;