E2E тестирование
E2E (End-to-End) тест проверяет полный пользовательский сценарий от начала до конца — через реальный браузер или HTTP-запросы к запущенному приложению со всеми его зависимостями.
Зачем нужно
E2E-тесты — единственный вид тестов, который гарантирует, что система работает так, как её видит конечный пользователь. Они обнаруживают ошибки интеграции между фронтендом и бэкендом, проблемы с конфигурацией и маршрутизацией, которые невидимы на уровне unit и integration тестов. При этом E2E-тесты дорогие — их должно быть мало, только для критических пользовательских сценариев.
Где используется
- Регрессионное тестирование перед релизом: «авторизация → корзина → оплата» работает
- Smoke-тесты после деплоя в production или staging-окружение
- Тестирование критических путей SPA (Single Page Application)
- API E2E-тесты: полный HTTP-цикл через запущенный Node.js-сервер
Основной контент
Виды E2E-тестирования
| Подход | Инструмент | Скорость | Уровень |
|---|---|---|---|
| Браузерный | Playwright, Cypress | Медленно | Полный UI |
| HTTP API | supertest + реальный сервер | Быстрее | Бэкенд |
| CLI | child_process | Быстро | Консольные приложения |
HTTP API E2E с реальным сервером
// server.js
const app = require('./app');
const server = app.listen(3001);
module.exports = server;
// e2e/auth.e2e.test.js
const request = require('supertest');
const server = require('../server');
afterAll( => server.close());
describe('Полный сценарий: регистрация и авторизация', () => {
let authToken;
test('1. Регистрирует нового пользователя', async () => {
const res = await request(server)
.post('/api/auth/register')
.send({ name: 'Alice', email: 'alice@test.com', password: 'Passw0rd!' });
expect(res.status).toBe(201);
expect(res.body.id).toBeDefined();
});
test('2. Авторизует пользователя и получает JWT', async () => {
const res = await request(server)
.post('/api/auth/login')
.send({ email: 'alice@test.com', password: 'Passw0rd!' });
expect(res.status).toBe(200);
expect(res.body.token).toBeDefined();
authToken = res.body.token;
});
test('3. Получает профиль с токеном', async () => {
const res = await request(server)
.get('/api/profile')
.set('Authorization', `Bearer ${authToken}`);
expect(res.status).toBe(200);
expect(res.body.email).toBe('alice@test.com');
});
test('4. Отклоняет запрос без токена', async () => {
const res = await request(server).get('/api/profile');
expect(res.status).toBe(401);
});
});
Playwright — браузерный E2E
npm install --save-dev @playwright/test
npx playwright install chromium
// e2e/login.spec.js
const { test, expect } = require('@playwright/test');
test('пользователь входит и видит дашборд', async ({ page }) => {
await page.goto('http://localhost:3000');
// Заполняем форму
await page.fill('[data-testid="email"]', 'user@test.com');
await page.fill('[data-testid="password"]', 'secret');
await page.click('[data-testid="submit"]');
// Проверяем что перешли на дашборд
await expect(page).toHaveURL(/\/dashboard/);
await expect(page.locator('h1')).toContainText('Добро пожаловать');
});
npx playwright test # запуск всех E2E-тестов
npx playwright test --ui # интерактивный режим
npx playwright show-report # HTML-отчёт
E2E в CI/CD
# .github/workflows/e2e.yml
name: E2E Tests
on: [push]
jobs:
e2e:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: test
options: >-
--health-cmd pg_isready
--health-interval 10s
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npm ci
- run: npm run db:migrate
env:
DATABASE_URL: postgres://postgres:test@localhost/test
- run: npm run test:e2e
env:
DATABASE_URL: postgres://postgres:test@localhost/test
Частые ошибки
- Слишком много E2E-тестов — каждый E2E-тест в 10-100 раз дороже unit-теста; покрывай только критические сценарии
- Флакающие тесты — асинхронные операции (анимации, задержки) без явного
waitForделают тест нестабильным - Запуск E2E на каждый коммит — E2E лучше запускать только при слиянии в main/master или перед релизом
- Жёсткие селекторы —
div:nth-child(3) > spanсломается при любом изменении разметки; используйdata-testidатрибуты - Не изолированное состояние — E2E-тесты должны создавать собственные данные и не зависеть от порядка запуска