globalSetup выполняется один раз до того как поднимаются любые браузерные воркеры, в основном процессе. Это значит что передавать JavaScript-объекты в тесты нельзя: данные шарятся через файлы на диске или через process.env. Самое частое применение: залогиниться один раз и сохранить результат через storageState, чтобы каждый тест в сьюте стартовал авторизованным без повторения флоу входа. Это руководство покрывает паттерн с auth-состоянием, несколько ролей пользователей с отдельными файлами хранения, наполнение базы данных, глобальный teardown и условный паттерн который пропускает повторный вход если свежий auth-файл уже существует.
Что такое глобальный setup
Playwright выполняет функцию globalSetup один раз до запуска всего тест-сьюта, и функцию globalTeardown один раз после завершения всего. Они работают в основном процессе, до того как поднимаются браузерные воркеры.
Глобальный setup нужен для:
- Аутентификации и сохранения
storageState(самое частое применение) - Наполнения тестовой базы данных базовыми данными
- Запуска мок-сервера или тестового сервера
- Генерации файлов тест-данных
Базовая конфигурация
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
globalSetup: require.resolve('./global-setup'),
globalTeardown: require.resolve('./global-teardown'),
use: {
baseURL: 'http://localhost:3000',
},
});Самое частое применение: сохранение auth-состояния
// global-setup.ts
import { chromium, FullConfig } from '@playwright/test';
async function globalSetup(config: FullConfig) {
const { baseURL } = config.projects[0].use;
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(`${baseURL}/login`);
await page.getByLabel('Email').fill(process.env.TEST_USER_EMAIL!);
await page.getByLabel('Password').fill(process.env.TEST_USER_PASSWORD!);
await page.getByRole('button', { name: 'Log in' }).click();
await page.waitForURL(`${baseURL}/dashboard`);
// сохраняем куки + localStorage для переиспользования
await page.context().storageState({ path: 'playwright/.auth/user.json' });
await browser.close();
}
export default globalSetup;// playwright.config.ts — используем сохранённый auth во всех тестах
use: {
storageState: 'playwright/.auth/user.json',
},Каждый тест теперь стартует уже авторизованным. Никаких шагов входа. Никаких настроек сессии в каждом тесте. Логин происходит один раз.
Несколько ролей пользователей
Для приложений с ролями администратора и обычного пользователя:
// global-setup.ts
async function globalSetup(config: FullConfig) {
const { baseURL } = config.projects[0].use;
const browser = await chromium.launch();
// сохраняем auth администратора
const adminPage = await browser.newPage();
await loginAs(adminPage, `${baseURL}`, process.env.ADMIN_EMAIL!, process.env.ADMIN_PASSWORD!);
await adminPage.context().storageState({ path: 'playwright/.auth/admin.json' });
await adminPage.close();
// сохраняем auth обычного пользователя
const userPage = await browser.newPage();
await loginAs(userPage, `${baseURL}`, process.env.USER_EMAIL!, process.env.USER_PASSWORD!);
await userPage.context().storageState({ path: 'playwright/.auth/user.json' });
await userPage.close();
await browser.close();
}
async function loginAs(page: Page, baseURL: string, email: string, password: string) {
await page.goto(`${baseURL}/login`);
await page.getByLabel('Email').fill(email);
await page.getByLabel('Password').fill(password);
await page.getByRole('button', { name: 'Log in' }).click();
await page.waitForURL(`${baseURL}/dashboard`);
}Разные auth-состояния используются в разных проектах:
// playwright.config.ts
projects: [
{
name: 'admin-tests',
use: { storageState: 'playwright/.auth/admin.json' },
testMatch: '**/admin/**/*.spec.ts',
},
{
name: 'user-tests',
use: { storageState: 'playwright/.auth/user.json' },
testMatch: '**/user/**/*.spec.ts',
},
],Наполнение базы данных в глобальном setup
// global-setup.ts
import { Pool } from 'pg';
async function globalSetup() {
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
// наполняем базовыми тест-данными один раз
await pool.query(`
INSERT INTO users (email, password_hash, role)
VALUES ('testuser@example.com', $1, 'user')
ON CONFLICT (email) DO NOTHING
`, [hashedPassword]);
await pool.end();
}Глобальный teardown
// global-teardown.ts
import { Pool } from 'pg';
async function globalTeardown() {
// очищаем тест-данные после всего сьюта
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
await pool.query("DELETE FROM users WHERE email LIKE '%@test.example.com'");
await pool.end();
// останавливаем серверы запущенные в globalSetup
// (если хранил ссылку в process или global)
}
export default globalTeardown;Передача данных между глобальным setup и тестами
Глобальный setup работает в отдельном процессе от тестов. Передать JavaScript-объекты напрямую нельзя. Варианты:
Файлы: сохраняй данные на диск в глобальном setup, читай в тестах.// global-setup.ts
import fs from 'fs';
async function globalSetup() {
const testData = { userId: '123', orderId: '456' };
fs.writeFileSync('playwright/.test-data.json', JSON.stringify(testData));
}// в тестах
import testData from '../playwright/.test-data.json';
test('uses seeded data', async ({ page }) => {
await page.goto(`/orders/${testData.orderId}`);
});process.env.KEY = value в глобальном setup. Доступны в воркер-процессах тестов. Подходят для простых значений: ID, токены.
Условный запуск глобального setup
Пропускай глобальный setup при запуске отдельных тестов локально:
// global-setup.ts
async function globalSetup() {
// пропускаем если auth-файл свежий
const authFile = 'playwright/.auth/user.json';
if (fs.existsSync(authFile)) {
const stats = fs.statSync(authFile);
const ageMinutes = (Date.now() - stats.mtimeMs) / 60000;
if (ageMinutes < 30) {
console.log('Auth state is recent, skipping login...');
return;
}
}
// иначе логинимся и сохраняем
// ...
}Повторные локальные запуски становятся быстрее: шаг логина выполняется только когда сохранённый auth отсутствует или устарел.
→ See also: Авторизация в Playwright через storageState (без логина в каждом тесте) | Фикстуры Playwright: от встроенных до кастомных | Изоляция тестов: почему каждый тест Playwright должен быть stateless