Modern QA2026Тестируемость и курирование тестов
Join

Course26 Testing Like a Senior

Foundations · Chapter 26

Тестируемость и курирование тестов

Updated Jul 2026

Системные мыслители влияют на качество ещё до написания тестов. Они формируют архитектуру так, чтобы она была тестируемой (чтобы тесты было легко писать и надёжно запускать), и курируют существующий тестовый набор (чтобы он оставался острым, а не разрастался в неуправляемую массу). Обе активности обладают большим рычагом, чем написание новых тестов.

Тестируемость как принцип проектирования

Антипаттерн: Система строится сначала, а затем QA пытается её протестировать. Тестирование затруднено, потому что сервисы тесно связаны, поведение недетерминированно и нет способа наблюдать за внутренним состоянием.

Паттерн: Тестируемость — это требование к проектированию, рассматриваемое во время ревью архитектуры наряду с производительностью, безопасностью и масштабируемостью.

Три столпа тестируемости

Внедрение зависимостей — Сервисы принимают свои зависимости в качестве параметров, а не создают их внутри. Это позволяет тестам подставлять вместо реальных баз данных, API и сервисов контролируемые тестовые двойники. Без внедрения зависимостей интеграционные тесты требуют всего продакшен-стека.

Наблюдаемость — Система предоставляет достаточно информации, чтобы тесты могли проверить поведение, не обращаясь к внутреннему состоянию. Структурированное логирование, потоки событий и тестовые хуки обеспечивают видимость того, что система сделала и почему. Если вы не можете это наблюдать — вы не можете это протестировать.

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

Удаление плохих тестов

Антипаттерн: Тестовый набор только растёт. Никто не удаляет тесты, потому что «а вдруг мы пропустим баг?» Набор становится медленнее, нестабильнее и сложнее в поддержке. Новые тесты добавляются; мёртвые тесты накапливаются.

Паттерн: Регулярное курирование тестового набора. У тестов есть стоимость (поддержка, время выполнения, когнитивная нагрузка) и ценность (пойманные баги, обеспечиваемая уверенность). Удаляйте тесты, где стоимость превышает ценность.

Категории тестов для удаления

Категория Описание Пример
Тавтологические Тесты, которые не могут упасть, или тестируют сам фреймворк/язык expect(true).toBe(true), мокирование функции и проверка, что мок был вызван
Дублирующее покрытие Несколько тестов, покрывающих один и тот же путь без дополнительной ценности Три теста, проверяющих успешный логин с валидными учётными данными
Детали реализации Тесты, которые ломаются при рефакторинге кода без изменения поведения Проверка вызовов внутренних методов, приватного состояния или CSS-классов
Перманентно пропущенные Тесты, помеченные @skip или @ignore месяцами без плана исправления Любой тест, пропущенный более двух спринтов

Анализ стоимости и ценности

Для каждого теста (или категории тестов) задайте вопросы:

  • Как часто он ловит реальные баги? (ценность)
  • Как часто он падает из-за нестабильности или проблем окружения? (стоимость шума)
  • Сколько времени он выполняется? (стоимость времени)
  • Сколько усилий требуется для его поддержки? (стоимость поддержки)

Если тест не поймал реального бага за шесть месяцев, выполняется 30 секунд и ломается каждый второй спринт из-за проблем окружения — удалите его.

Ключевые выводы

  • Тестируемость — это требование к проектированию, а не запоздалая мысль; отстаивайте внедрение зависимостей, наблюдаемость и детерминизм во время ревью архитектуры
  • У тестов есть стоимость (поддержка, скорость, когнитивная нагрузка) и ценность (пойманные баги, уверенность) — курируйте соответственно
  • Удаляйте тавтологические тесты, дублирующее покрытие, тесты на детали реализации и перманентно пропущенные тесты
  • Регулярное курирование тестов обладает большим рычагом, чем написание новых тестов в зрелом наборе
  • Если тест не ловил реальных багов месяцами и требует времени на поддержку — он не приносит ценности