Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Пирамида тестирования: сколько каких тестов писать

Пирамида тестирования: пропорции unit, integration и e2e

Пирамида тестирования: уровни, стоимость и скорость, обратная пирамида как антипаттерн, практические пропорции и место контрактных тестов.

Прямой ответ

Пирамида тестирования — модель распределения тестов по уровням: внизу много быстрых и дешёвых unit-тестов, выше меньше интеграционных, на вершине немного сквозных (end-to-end). Смысл не в точных числах, а в принципе: чем выше уровень, тем дороже тест и тем меньше их должно быть.

Уровни и их свойства:

Уровень Что проверяет Скорость Локализация ошибки
Unit Отдельная функция или класс Миллисекунды Точная
Интеграционный Модуль с реальной БД, очередью, API Секунды Хорошая
Контрактный Совместимость двух сервисов Секунды Хорошая
E2E Сценарий пользователя во всей системе Десятки секунд — минуты Плохая
Ручной / исследовательский То, что автоматизировать дорого Очень медленно —

Почему пропорция именно такая:

  1. Скорость обратной связи. Тысяча unit-тестов выполняется за минуту; сотня e2e — за полчаса. Разработчик запускает первое десятки раз в день, второе — перед выкаткой.
  2. Локализация. Падение unit-теста указывает на конкретную функцию. Падение e2e-сценария «оформление заказа» может быть вызвано десятком причин.
  3. Стоимость поддержки. E2E-тесты ломаются от изменений интерфейса, таймингов и данных. Их поддержка стоит дороже написания — см. flaky-тесты.
  4. Надёжность. Чем больше внешних компонентов участвует, тем выше вероятность ложного падения.

Обратная пирамида (много e2e, мало unit) — распространённый антипаттерн. Её признаки: прогон занимает час, падения разбирают «перезапуском», разработчики боятся менять код, потому что не понимают, что сломалось. Часто она возникает исторически: e2e-тесты пишут QA-инженеры, а unit-тесты не пишутся вовсе.

# маркеры pytest позволяют запускать уровни раздельно
# pyproject.toml
[tool.pytest.ini_options]
markers = [
    "unit: быстрые тесты без внешних зависимостей",
    "integration: требуется БД или контейнер",
    "e2e: сквозной сценарий, запуск перед выкаткой",
]
pytest -m unit                 # на каждое сохранение
pytest -m "unit or integration"  # на каждый коммит
pytest -m e2e                  # перед выкаткой

Практика: как применить в реальном проекте

1. Ориентиры пропорций. Точных чисел не существует, рабочие диапазоны: unit 60–80 % от числа тестов, интеграционные 15–30 %, e2e 5–10 %. Важнее другое: время прогона unit-тестов — минуты, полного — десятки минут.

2. Unit-тест — это не «тест маленького класса». Критерий — отсутствие внешних зависимостей и детерминированность. Расчёт скидки, парсинг, бизнес-правила, преобразования данных. Внешние зависимости подменяют двойниками — см. тестовые двойники.

3. Интеграционные тесты — на границах. Реальная БД проверяет SQL, миграции, ограничения и транзакции. Реальная очередь — семантику доставки. Контейнеры позволяют делать это воспроизводимо — см. интеграционные тесты в Docker.

4. E2E — только ключевые сценарии. Регистрация, оплата, отмена. Десять-двадцать сценариев, а не двести. Их цель — убедиться, что система собирается в работающее целое, а не проверить каждую ветку.

5. Контрактные тесты закрывают промежуток. Они проверяют совместимость сервисов без развёртывания обоих — это дешевле e2e и надёжнее. Подробно — в статье про Pact.

6. Не всё нужно автоматизировать. Проверка визуальной части, удобства, формулировок — задача ручного тестирования. Попытка автоматизировать это даёт дорогие и хрупкие тесты.

Рекомендации:

  1. Измеряйте время прогона по уровням. Если unit-прогон занимает 20 минут, пирамида уже нарушена: либо тесты не изолированы, либо они делают лишнюю работу.
  2. Пишите тест на том уровне, где дефект дешевле всего ловится. Ошибка в расчёте — unit; ошибка в запросе — интеграционный; ошибка в сборке системы — e2e.
  3. Не дублируйте проверки между уровнями. Если правило проверено unit-тестом, e2e-сценарий должен проверять связность, а не то же правило ещё раз.
  4. Пересматривайте набор e2e. Сценарии, которые не падали ни разу за год и не менялись, вероятно, проверяют не то, что ломается.
  5. Следите за обратной связью. Тест, результат которого разработчик ждёт дольше пяти минут, фактически не участвует в процессе.

Практический сценарий: разворот обратной пирамиды

Контекст: в проекте было 340 e2e-тестов в Selenium и 60 unit-тестов. Полный прогон занимал 2 часа 10 минут, в среднем 11 % прогонов падали без изменений кода.

  1. Измерение. Разбор показал: 78 % e2e-тестов проверяли правила расчёта и валидации, доступные на уровне функций. Только 41 тест действительно проверял сквозной сценарий.
  2. Шаг 1. Правила расчёта и валидации перенесли в unit-тесты: 210 новых тестов, время прогона 40 секунд.
  3. Шаг 2. Взаимодействие с базой и очередями покрыли интеграционными тестами в контейнерах: 85 тестов, 4 минуты.
  4. Шаг 3. В e2e оставили 38 сценариев, соответствующих ключевым пользовательским путям; остальные удалили.
  5. Шаг 4. Разделили прогоны: unit — на каждое сохранение, плюс интеграционные — на каждый коммит, e2e — перед выкаткой и ночью.
  6. Результат. Обратная связь по unit-тестам — 40 секунд вместо ожидания ночного прогона. Доля ложных падений снизилась с 11 до 2 %. Время полного прогона — 26 минут. Число дефектов, найденных до продакшена, за квартал выросло, потому что разработчики начали запускать тесты регулярно.

Вывод: пирамида — это про скорость обратной связи. Перенос проверок на уровень ниже окупается не экономией машинного времени, а тем, что тесты начинают запускать.

FAQ

Обязательна ли форма пирамиды? Форма — следствие свойств уровней: стоимости, скорости и локализации. Для приложений с тонкой бизнес-логикой и сложным интерфейсом разумная пропорция смещается вверх; для библиотек и алгоритмических систем — вниз.

Что такое «мороженое» (ice cream cone)? Разновидность обратной пирамиды: много ручных проверок и e2e поверх малого числа автоматизированных тестов. Признак — тестирование в основном выполняется людьми перед релизом.

Нужны ли e2e-тесты вообще, если есть интеграционные и контрактные? Да, но немного. Они проверяют то, что не проверяется иначе: сборку системы, конфигурацию окружения, поведение под нагрузкой реального клиента.

Как понять, что тестов на уровне достаточно? Косвенные признаки: дефекты соответствующего типа перестают доходить до следующих уровней, а падение теста даёт понятную локализацию. Если дефект в расчёте обнаруживается в e2e — unit-уровень недопокрыт.

Источники: Martin Fowler (Practical Test Pyramid), pytest docs (markers), Google Testing Blog — ссылки в шапке.