Перейти к основному содержимому

Глобальная настройка и завершение

Введение

Есть два способа настроить global setup и teardown: использовать файл global setup и указать его в конфиге через globalSetup, либо использовать зависимости проектов. При использовании зависимостей проектов вы определяете проект, который запускается перед всеми остальными проектами. Это рекомендуемый подход, так как он лучше интегрируется с раннером Playwright: global setup будет виден в HTML-отчёте, будут записываться трассы, и можно будет использовать фикстуры. Подробное сравнение двух подходов — в таблице ниже.

ВозможностьЗависимости проектов (рекомендуется)globalSetup (опция конфига)
Запускается перед всеми тестами✅ Да✅ Да
Видимость в HTML-отчёте✅ Показано как отдельный проект❌ Не показано
Запись трасс✅ Доступна полная трасса❌ Не поддерживается
Фикстуры Playwright✅ Полностью поддерживаются❌ Не поддерживаются
Управление браузером✅ Через фикстуру browser❌ Полностью вручную через browserType.launch()
Параллелизм и повторы✅ Поддерживаются через стандартную конфигурацию❌ Не применимо
Опции конфига вроде headless или testIdAttribute✅ Применяются автоматически❌ Игнорируются

Вариант 1: Зависимости проекта

Зависимости проекта — это список проектов, которые должны быть выполнены перед запуском тестов в другом проекте. Они могут быть полезны для настройки глобальных действий, чтобы один проект зависел от выполнения другого. Использование зависимостей позволяет глобальной настройке создавать трассировки и другие артефакты.

Настройка

Сначала мы добавляем новый проект с именем 'setup db'. Затем мы задаем ему свойство testProject.testMatch, чтобы сопоставить файл с именем global.setup.ts:

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

export default defineConfig({
testDir: './tests',
// ...
projects: [
{
name: 'setup db',
testMatch: /global\.setup\.ts/,
},
// {
// другой проект
// }
]
});

Затем мы добавляем свойство testProject.dependencies к нашим проектам, которые зависят от проекта настройки, и передаем в массив имя нашего проекта-зависимости, который мы определили на предыдущем шаге:

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

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

В этом примере проект 'chromium with db' зависит от проекта 'setup db'. Затем мы создаем тест настройки, который хранится на корневом уровне вашего проекта (обратите внимание, что код настройки и завершения должен быть определен как обычные тесты с помощью вызова функции test()):

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

setup('create new database', async ({ }) => {
console.log('creating new database...');
// Инициализация базы данных
});
tests/menu.spec.ts
import { test, expect } from '@playwright/test';

test('menu', async ({ page }) => {
// Ваш тест, который зависит от базы данных
});

Завершение

Вы можете завершить настройку, добавив свойство testProject.teardown к вашему проекту настройки. Это будет выполнено после того, как все зависимые проекты будут выполнены.

Сначала мы добавляем свойство testProject.teardown к нашему проекту настройки с именем 'cleanup db', которое мы дали нашему проекту завершения на предыдущем шаге:

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

Затем мы создаем файл global.teardown.ts в каталоге тестов вашего проекта. Он будет использоваться для удаления данных из базы данных после выполнения всех тестов.

tests/global.teardown.ts
import { test as teardown } from '@playwright/test';

teardown('delete database', async ({ }) => {
console.log('deleting test database...');
// Удаление базы данных
});

Фильтрация тестов

Все опции фильтрации тестов, такие как --grep/--grep-invert, --shard, фильтрация напрямую по позиции (location) в командной строке или использование test.only(), напрямую выбирают основные тесты, которые будут запущены. Если эти тесты относятся к проекту с зависимостями, то будут запущены и все тесты из этих зависимостей.

Вы можете передать опцию командной строки --no-deps, чтобы игнорировать все зависимости и teardown’ы. Тогда будут запущены только проекты, которые вы выбрали напрямую.

Больше примеров

Для более подробных примеров ознакомьтесь с:

Вариант 2: Настройка globalSetup и globalTeardown

Вы можете использовать опцию globalSetup в файле конфигурации, чтобы настроить что-то один раз перед запуском всех тестов. Глобальный файл настройки должен экспортировать одну функцию, которая принимает объект конфигурации. Эта функция будет выполнена один раз перед всеми тестами.

Аналогично, используйте globalTeardown, чтобы выполнить что-то один раз после всех тестов. В качестве альтернативы, пусть globalSetup возвращает функцию, которая будет использоваться как глобальное завершение. Вы можете передавать данные, такие как номер порта, токены аутентификации и т.д., из вашей глобальной настройки в ваши тесты, используя переменные окружения.

примечание

Учтите, что у globalSetup и globalTeardown не хватает некоторых возможностей — подробное сравнение см. в разделе введение. Вместо этого рассмотрите использование зависимостей проектов, чтобы получить поддержку всех возможностей.

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

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

Пример

Вот пример глобальной настройки, которая аутентифицируется один раз и повторно использует состояние аутентификации в тестах. Она использует опции baseURL и storageState из файла конфигурации.

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;

Укажите globalSetup, baseURL и storageState в файле конфигурации.

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, который был заполнен глобальной настройкой.

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

test('test', async ({ page }) => {
await page.goto('/');
// Вы вошли в систему!
});

Вы можете сделать произвольные данные доступными в ваших тестах из вашего файла глобальной настройки, установив их как переменные окружения через process.env.

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

async function globalSetup(config: FullConfig) {
process.env.FOO = 'some data';
// Или более сложная структура данных в формате JSON:
process.env.BAR = JSON.stringify({ some: 'data' });
}

export default globalSetup;

Тесты имеют доступ к свойствам process.env, установленным в глобальной настройке.

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

test('test', async ({ page }) => {
// переменные окружения, которые установлены в globalSetup, доступны только внутри test().
const { FOO, BAR } = process.env;

// Свойства FOO и BAR заполнены.
expect(FOO).toEqual('some data');

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

Захват трассировки ошибок во время глобальной настройки

В некоторых случаях может быть полезно захватить трассировку ошибок, возникших во время глобальной настройки. Для этого вы должны начать трассировку в вашей настройке и убедиться, что вы остановите трассировку, если ошибка произойдет до того, как она будет выброшена. Это можно сделать, обернув вашу настройку в блок try...catch. Вот пример, который расширяет пример глобальной настройки для захвата трассировки.

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;