Что такое Playwright?
Playwright — современный фреймворк автоматизации браузеров от Microsoft. Он предоставляет единый API для управления браузерами Chromium, Firefox и WebKit. Выпущенный в 2020 году, быстро стал самым популярным выбором для новых проектов автоматизации.
Почему Playwright?
| Возможность | Playwright | Selenium |
|---|---|---|
| Auto-waiting | Встроенный | Ручные ожидания |
| Мультибраузерность | Chromium, Firefox, WebKit | Отдельные драйверы |
| Скорость | Очень высокая | Средняя |
| Локаторы | По роли, тексту, test-id | CSS, XPath, ID |
| Отладка | Trace Viewer, Inspector | Только скриншоты |
| API-тестирование | Встроенное | Отдельный инструмент |
| Codegen | Встроенный | Недоступен |
| Параллельное выполнение | Нативное | Требует Grid |
Настройка Playwright
JavaScript/TypeScript
npm init playwright@latest
Python
pip install playwright
playwright install
Написание первого теста
import { test, expect } from '@playwright/test';
test('пользователь может войти и увидеть дашборд', async ({ page }) => {
await page.goto('https://app.example.com/login');
await page.fill('[data-testid="email"]', 'admin@test.com');
await page.fill('[data-testid="password"]', 'secret123');
await page.click('[data-testid="submit"]');
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('.welcome')).toHaveText('Welcome, Admin');
});
test('невалидный логин показывает ошибку', async ({ page }) => {
await page.goto('https://app.example.com/login');
await page.fill('[data-testid="email"]', 'wrong@test.com');
await page.fill('[data-testid="password"]', 'wrongpass');
await page.click('[data-testid="submit"]');
await expect(page.locator('.error')).toHaveText('Неверные учётные данные');
});
Мощные локаторы
Локаторы по роли (Рекомендуется)
await page.getByRole('button', { name: 'Войти' }).click();
await page.getByRole('textbox', { name: 'Email' }).fill('admin@test.com');
await page.getByLabel('Email').fill('admin@test.com');
await page.getByPlaceholder('Введите email').fill('admin@test.com');
await page.getByText('Войти').click();
await page.getByTestId('login-submit').click();
Цепочки и фильтрация локаторов
await page.locator('.product-card').filter({ hasText: 'Беспроводная мышь' })
.getByRole('button', { name: 'В корзину' }).click();
await page.locator('.product-card').nth(0).click();
await page.locator('.product-card').first().click();
Auto-Waiting
// Ручные ожидания не нужны — Playwright справляется сам
await page.click('#submit');
// Playwright ждёт: видимость, стабильность, активность, приём событий
await expect(page.locator('.result')).toHaveText('Успех');
// Playwright повторяет попытки до прохождения ассерта (в пределах таймаута)
Web-First ассерты
await expect(page).toHaveTitle('Dashboard');
await expect(page).toHaveURL(/dashboard/);
await expect(page.locator('.status')).toHaveText('Активен');
await expect(page.locator('.item')).toHaveCount(5);
await expect(page.locator('#btn')).toBeVisible();
await expect(page.locator('#btn')).toBeEnabled();
await expect(page.locator('#input')).toHaveValue('hello');
Конфигурация
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30000,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 4 : undefined,
reporter: [['html'], ['junit', { outputFile: 'results.xml' }]],
use: {
baseURL: 'https://app.example.com',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
{ name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
{ name: 'mobile-safari', use: { ...devices['iPhone 13'] } },
],
});
Продвинутые возможности
Trace Viewer
npx playwright test
npx playwright show-trace trace.zip
Trace показывает: скриншоты на каждом шаге, снимки DOM, сетевые запросы, логи консоли и исходный код.
Codegen — Запись тестов
npx playwright codegen https://app.example.com
Codegen открывает браузер и записывает ваши действия, генерируя тест-код в реальном времени.
API-тестирование (Встроенное)
test('создать пользователя через API', async ({ request }) => {
const response = await request.post('/api/users', {
data: { name: 'Test User', email: 'test@example.com' },
});
expect(response.ok()).toBeTruthy();
const user = await response.json();
expect(user.name).toBe('Test User');
});
test('админ создаёт пользователя через API, проверяет в UI', async ({ page, request }) => {
const response = await request.post('/api/users', {
data: { name: 'Новый пользователь', email: 'new@test.com' }
});
const user = await response.json();
await page.goto(`/admin/users/${user.id}`);
await expect(page.locator('.user-name')).toHaveText('Новый пользователь');
});
Перехват сетевых запросов
await page.route('/api/users', route => {
route.fulfill({
status: 200,
body: JSON.stringify([{ id: 1, name: 'Mock User' }]),
});
});
const [response] = await Promise.all([
page.waitForResponse('/api/checkout'),
page.click('#pay-button'),
]);
expect(response.status()).toBe(200);
Множественные контексты браузера
test('два пользователя взаимодействуют в реальном времени', async ({ browser }) => {
const adminContext = await browser.newContext();
const userContext = await browser.newContext();
const adminPage = await adminContext.newPage();
const userPage = await userContext.newPage();
await adminPage.goto('/admin/chat');
await adminPage.fill('#message', 'Привет пользователь!');
await adminPage.click('#send');
await userPage.goto('/chat');
await expect(userPage.locator('.message')).toHaveText('Привет пользователь!');
await adminContext.close();
await userContext.close();
});
Запуск тестов
npx playwright test # Все тесты
npx playwright test tests/login.spec.ts # Конкретный файл
npx playwright test --project=firefox # Конкретный браузер
npx playwright test --headed # С интерфейсом
npx playwright test --ui # Интерактивный режим
npx playwright test --debug tests/login.spec.ts # Отладка
npx playwright show-report # HTML-отчёт
Упражнение: Постройте suite тестов на Playwright
Создайте полный набор тестов Playwright:
- Инициализируйте проект с TypeScript
- Настройте 3 браузерных проекта (Chrome, Firefox, WebKit)
- Создайте Page Objects для Login, Dashboard и Settings
- Напишите 8 тестов: логин (валидный/невалидный), навигация, форма, API + UI, мок сети, мульти-viewport, сравнение скриншотов
- Настройте traces и скриншоты при падении
- Запустите тесты параллельно во всех браузерах
- Сгенерируйте и просмотрите HTML-отчёт
Ключевые выводы
- Auto-waiting Playwright устраняет большинство нестабильных тестов из-за проблем с таймингом
- Локаторы по роли — самая устойчивая стратегия поиска элементов
- Trace Viewer предоставляет непревзойдённые возможности отладки
- Встроенное API-тестирование позволяет смешивать быструю API-подготовку с UI-проверкой
- Codegen записывает взаимодействия с браузером и генерирует тест-код
- Нативное параллельное выполнение в Chromium, Firefox и WebKit
- Фикстуры Playwright естественно интегрируются с Page Object Model