Тестируемость и курирование тестов
Updated Jul 2026
Системные мыслители влияют на качество ещё до написания тестов. Они формируют архитектуру так, чтобы она была тестируемой (чтобы тесты было легко писать и надёжно запускать), и курируют существующий тестовый набор (чтобы он оставался острым, а не разрастался в неуправляемую массу). Обе активности обладают большим рычагом, чем написание новых тестов.
Тестируемость как принцип проектирования
Антипаттерн: Система строится сначала, а затем QA пытается её протестировать. Тестирование затруднено, потому что сервисы тесно связаны, поведение недетерминированно и нет способа наблюдать за внутренним состоянием.
Паттерн: Тестируемость — это требование к проектированию, рассматриваемое во время ревью архитектуры наряду с производительностью, безопасностью и масштабируемостью.
Три столпа тестируемости
Внедрение зависимостей — Сервисы принимают свои зависимости в качестве параметров, а не создают их внутри. Это позволяет тестам подставлять вместо реальных баз данных, API и сервисов контролируемые тестовые двойники. Без внедрения зависимостей интеграционные тесты требуют всего продакшен-стека.
Наблюдаемость — Система предоставляет достаточно информации, чтобы тесты могли проверить поведение, не обращаясь к внутреннему состоянию. Структурированное логирование, потоки событий и тестовые хуки обеспечивают видимость того, что система сделала и почему. Если вы не можете это наблюдать — вы не можете это протестировать.
Детерминизм — При одинаковых входных данных система даёт одинаковые результаты. Недетерминированное поведение (случайные значения, системное время, неупорядоченные коллекции) создаёт нестабильные тесты. Проектируйте для детерминизма: внедряйте часы и генераторы случайных чисел, сортируйте выходные данные, когда порядок не важен, используйте стабильные идентификаторы.
Удаление плохих тестов
Антипаттерн: Тестовый набор только растёт. Никто не удаляет тесты, потому что «а вдруг мы пропустим баг?» Набор становится медленнее, нестабильнее и сложнее в поддержке. Новые тесты добавляются; мёртвые тесты накапливаются.
Паттерн: Регулярное курирование тестового набора. У тестов есть стоимость (поддержка, время выполнения, когнитивная нагрузка) и ценность (пойманные баги, обеспечиваемая уверенность). Удаляйте тесты, где стоимость превышает ценность.
Категории тестов для удаления
| Категория | Описание | Пример |
|---|---|---|
| Тавтологические | Тесты, которые не могут упасть, или тестируют сам фреймворк/язык | expect(true).toBe(true), мокирование функции и проверка, что мок был вызван |
| Дублирующее покрытие | Несколько тестов, покрывающих один и тот же путь без дополнительной ценности | Три теста, проверяющих успешный логин с валидными учётными данными |
| Детали реализации | Тесты, которые ломаются при рефакторинге кода без изменения поведения | Проверка вызовов внутренних методов, приватного состояния или CSS-классов |
| Перманентно пропущенные | Тесты, помеченные @skip или @ignore месяцами без плана исправления |
Любой тест, пропущенный более двух спринтов |
Анализ стоимости и ценности
Для каждого теста (или категории тестов) задайте вопросы:
- Как часто он ловит реальные баги? (ценность)
- Как часто он падает из-за нестабильности или проблем окружения? (стоимость шума)
- Сколько времени он выполняется? (стоимость времени)
- Сколько усилий требуется для его поддержки? (стоимость поддержки)
Если тест не поймал реального бага за шесть месяцев, выполняется 30 секунд и ломается каждый второй спринт из-за проблем окружения — удалите его.
Ключевые выводы
- Тестируемость — это требование к проектированию, а не запоздалая мысль; отстаивайте внедрение зависимостей, наблюдаемость и детерминизм во время ревью архитектуры
- У тестов есть стоимость (поддержка, скорость, когнитивная нагрузка) и ценность (пойманные баги, уверенность) — курируйте соответственно
- Удаляйте тавтологические тесты, дублирующее покрытие, тесты на детали реализации и перманентно пропущенные тесты
- Регулярное курирование тестов обладает большим рычагом, чем написание новых тестов в зрелом наборе
- Если тест не ловил реальных багов месяцами и требует времени на поддержку — он не приносит ценности