Пирамида тестирования
Пирамида тестирования — визуальная модель, описывающая оптимальное соотношение видов тестов: много быстрых unit-тестов в основании, меньше integration и совсем мало медленных E2E на вершине.
Зачем нужно
Без модели команды либо пишут только E2E (медленно, хрупко, дорого), либо только unit (быстро, но не проверяют интеграцию). Пирамида задаёт стратегию: вложи бюджет тестирования туда, где максимальная отдача при минимальных затратах.
Где используется
- Планирование тестовой стратегии нового проекта
- Аудит существующего тест-сьюта (перевёрнутая пирамида — anti-pattern)
- Обсуждение соотношения тестов в команде
Основной контент
Классическая пирамида (Mike Cohn)
/─────────\
/ E2E \ ← мало, медленные, дорогие
/─────────────\
/ Integration \ ← средне, реальные зависимости
/─────────────────\
/ Unit Tests \ ← много, быстрые, изолированные
/─────────────────────\
Характеристики каждого уровня
| Уровень | Кол-во | Скорость | Цена поддержки | Что проверяет |
|---|---|---|---|---|
| Unit | 70% | Миллисекунды | Низкая | Логика функций |
| Integration | 20% | Секунды | Средняя | Взаимодействие слоёв |
| E2E | 10% | Минуты | Высокая | Пользовательские сценарии |
Примеры для каждого уровня
// Unit — изолированная функция
test('calculateTotal прибавляет tax', () => {
expect(calculateTotal({ price: 100, taxRate: 0.2 })).toBe(120);
});
// Integration — сервис + репозиторий + БД (SQLite in-memory)
test('UserService.create сохраняет пользователя в БД', async () => {
const user = await userService.create({ name: 'Alice', email: 'alice@test.com' });
const found = await db('users').where({ id: user.id }).first;
expect(found.name).toBe('Alice');
});
// E2E — полный сценарий через браузер
test('пользователь регистрируется и видит dashboard', async ({ page }) => {
await page.goto('/register');
await page.fill('[data-testid="email"]', 'alice@test.com');
await page.fill('[data-testid="password"]', 'Pass123!');
await page.click('[data-testid="submit"]');
await expect(page).toHaveURL('/dashboard');
});
Антипаттерн: перевёрнутая пирамида (Ice Cream Cone)
/─────────────────────\
/ E2E \ ← много медленных E2E
/─────────────────────────\
/ Integration \
/─────────────────────────────\
Unit ← мало unit
Симптомы: CI работает 40 минут, тесты регулярно flaky, разработчики боятся запускать тесты.
Модификации пирамиды
- Testing Trophy (Kent C. Dodds) — акцент на integration тесты для фронтенда: они дают больший ROI чем чистые unit при тестировании компонентов
- Honeycomb (Spotify) — для микросервисов: меньше E2E, больше service-integration
Частые ошибки
- Копирование unit-логики в E2E — E2E тест на валидацию каждого поля формы — это перевёрнутая пирамида; покрывай детали unit-тестами
- Нет integration тестов — пропуск среднего слоя значит что баги на стыке сервисов ловятся только в E2E или production
- Жёсткое следование 70/20/10 — это ориентир, а не закон; для конкретного проекта соотношение может быть другим