Playwright: обзор
Playwright — E2E testing framework от Microsoft с поддержкой Chromium, Firefox и WebKit из одного API, встроенным авто-ожиданием и мощными инструментами для отладки.
Зачем нужно
Playwright решает главные проблемы E2E тестирования: авто-ожидание встроено в каждое действие, кроссбраузерность из коробки, встроенные инструменты трассировки и скриншотов. TypeScript поддерживается нативно без дополнительных плагинов.
Где используется
- E2E тесты для веб-приложений с поддержкой нескольких браузеров
- Component testing для React/Vue/Angular
- API тестирование через
requestfixture - Visual regression testing в связке со snapshot assertions
Основной контент
Установка
npm init playwright@latest
# Создаёт playwright.config.ts, example tests, .github/workflows
# Или в существующий проект
npm install --save-dev @playwright/test
npx playwright install # скачивает браузеры
Базовый тест
// tests/example.spec.ts
import { test, expect } from '@playwright/test';
test('главная страница имеет заголовок', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example/);
});
test('форма поиска работает', async ({ page }) => {
await page.goto('/');
await page.getByPlaceholder('Поиск...').fill('playwright');
await page.getByRole('button', { name: 'Найти' }).click();
await expect(page.getByTestId('search-results')).toBeVisible;
});
Ключевые локаторы
// Приоритет: accessibility-first подход
page.getByRole('button', { name: 'Submit' }) // по роли
page.getByLabel('Email') // по label
page.getByPlaceholder('Enter email') // по placeholder
page.getByText('Sign in') // по тексту
page.getByTestId('submit-btn') // по data-testid
page.locator('[data-testid="submit"]') // CSS/XPath
playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry', // трассировка при retry
screenshot: 'only-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
{ name: 'mobile', use: { ...devices['iPhone 14'] } },
],
});
Fixture для авторизации
// tests/fixtures.ts
import { test as base } from '@playwright/test';
import { LoginPage } from './pages/LoginPage';
export const test = base.extend({
authenticatedPage: async ({ page }, use) => {
const loginPage = new LoginPage(page);
await loginPage.goto;
await loginPage.login(process.env.TEST_EMAIL!, process.env.TEST_PASSWORD!);
await use(page);
},
});
// В тесте
test('защищённая страница', async ({ authenticatedPage: page }) => {
await page.goto('/dashboard');
await expect(page.getByTestId('user-menu')).toBeVisible;
});
Отладка
npx playwright test --debug # пошаговый дебаггер
npx playwright codegen http://localhost:3000 # запись тестов
npx playwright show-report # HTML-отчёт
npx playwright show-trace trace.zip # просмотр трассировки
Частые ошибки
page.waitForTimeoutвместо assertions — заменяй всеsleepнаexpect(locator).toBeVisible— Playwright ждёт сам- Нет
baseURLв конфиге — в каждом тесте приходится писать полный URL; задай один раз в конфиге - Запуск без
--project— по умолчанию запускает все браузеры; в разработке используй--project chromium - Тест создаёт данные без cleanup — используй
test.afterEachили API-сброс для изоляции
Связанные темы
- _MOC Тестирование
- E2E тестирование
- E2E -- паттерны и антипаттерны
- Page Object Model
- Cypress -- установка и основы
- ATDD -- Acceptance Test-Driven Development