Данные, изоляция и авторизация один раз
Изоляция и тестовые данные определяют, будут ли тесты стабильными. А авторизацию можно сделать один раз на весь прогон.
Storage state — сохранённое состояние сессии (cookie и localStorage), которое можно записать один раз после входа и подставлять в тесты, минуя повторную авторизацию.
Изоляция: каждый тест с чистого листа
Playwright по умолчанию даёт каждому тесту свежий контекст — без чужих cookie и данных. Это значит, что тесты не влияют друг на друга и могут идти в любом порядке и параллельно. Не нарушайте это: не полагайтесь на данные, оставленные другим тестом, иначе вернётся проблема флаки из прошлого раздела.
Тестовые данные: делайте их уникальными
Если два теста регистрируют пользователя с email [email protected], при параллельном запуске один из них упадёт — email уже занят. Решение — уникальные данные на каждый прогон.
// уникальный email на основе времени
const email = `user-${Date.now()}@example.com`;
await page.getByLabel('Email').fill(email);Проблема: вход в каждом тесте — это дорого
Если двадцать тестов начинаются с beforeEach, где происходит вход (заполнить форму, нажать кнопку, дождаться редиректа), вы платите за авторизацию двадцать раз. На большом наборе это заметные минуты, потраченные впустую на одни и те же шаги.
Решение: авторизоваться один раз
Идея: войти однажды в setup-проекте, сохранить состояние сессии в файл, а все тесты запускать уже с этим состоянием. Сначала setup-тест, который логинится и сохраняет storage state:
// auth.setup.ts
import { test as setup } from '@playwright/test';
const authFile = 'playwright/.auth/user.json';
setup('авторизация', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('[email protected]');
await page.getByLabel('Пароль').fill('secret');
await page.getByRole('button', { name: 'Войти' }).click();
await page.waitForURL('/dashboard');
// сохраняем cookie и localStorage в файл
await page.context().storageState({ path: authFile });
});Затем в конфиге указываем: брать это состояние для всех тестов, а setup выполнять до них.
// playwright.config.ts (фрагмент)
projects: [
{ name: 'setup', testMatch: /auth\.setup\.ts/ },
{
name: 'chromium',
use: { storageState: 'playwright/.auth/user.json' },
dependencies: ['setup'], // сначала setup, потом тесты
},
],Теперь каждый тест стартует уже авторизованным — без формы входа. Вход выполнился один раз.
test('видит личный кабинет', async ({ page }) => {
await page.goto('/dashboard'); // уже залогинены!
await expect(page.getByText('Иван Петров')).toBeVisible();
});Что хранить отдельно
| Сценарий | Подход |
| Обычный пользователь | один storage state на всех |
| Разные роли (admin, user) | отдельный файл состояния на роль |
| Тест самого входа/выхода | без storage state, логиниться в тесте |
Тесты, которые проверяют сам процесс входа, разумеется, должны логиниться вручную — для них переиспользование сессии не подходит, иначе они проверяли бы не то. И не забудьте добавить папку playwright/.auth/ в .gitignore: в ней лежат настоящие токены сессии.
Итог
- Каждый тест получает чистый контекст — не полагайтесь на чужие данные.
- Делайте тестовые данные уникальными (например, email с меткой времени).
- Storage state позволяет авторизоваться один раз и переиспользовать сессию.
- Для разных ролей — разные файлы состояния; тесты входа логинятся вручную.