Тема: Прикладная часть 5. Мутационное тестирование спецификаций
Уровень сложности: Средний (Средний)
Расчётное время изучения: 3-4 часа
Предварительные требования: Знакомство с дисциплиной фактов из части 9 первого тома (формат Given/When/Then)
Понимание антипаттернов SDD из части 20
Базовые навыки работы с командной строкой Linux и Python 3
Понимание структуры JSON и принципов работы JSON Schema
Цели обучения: Успешно запускать генератор вырожденных спецификаций и обеспечивать детерминированность генерации (проверку через seed).
Измерять устойчивость валидаторного контура с помощью векторной метрики иммунитета (strict_reject_rate, depth_of_diagnostics, recovery_time).
Связывать каждый сгенерированный мутант с конкретным шагом сценария Given/When/Then и правилом JSON Schema.
Формировать корректный и воспроизводимый ревьюируемый след (отчет о дымовом тестировании) для CI и SDD.
Обзор: Мутационное тестирование спецификаций (или «вакцинация валидаторов») — это практика проверки устойчивости валидатора. Вместо того чтобы проверять систему на корректных данных, техника целенаправленно «портит» базовую спецификацию, используя заранее определенные операторы мутации (например, удаление полей или создание циклов). Валидатор должен поймать этот дефект на строго определенном шаге и выдать точный код ошибки. Данный подход превращает валидатор из простой проверки синтаксиса в инструмент анатомической диагностики, гарантируя, что некорректные инциденты не приведут к каскадным сбоям в продакшене.
Ключевые концепции: Мутационное тестирование (mutation testing): Техника тестирования, при которой эталонный артефакт контролируемо изменяется (портится), а тестовый контур обязан обнаружить этот дефект и отклонить его.
Метрика иммунитета (immunity score): Векторная метрика устойчивости валидатора, состоящая из трех компонент: strict_reject_rate (доля строго отклоненных кейсов), depth_of_diagnostics (полезная глубина диагностики) и recovery_time (время возврата стабильного вердикта).
Фабрика мутаций (mutation factory): Детерминированный генератор, который берет корректную базовую спецификацию (base_spec.json) и применяет к ней каталог операторов порчи, сохраняя воспроизводимость через зерно генерации (seed).
Операторы мутации (mutation operators): Типы контролируемых дефектов. Основные классы: Nullify (обнуление полей), FutureTime (временные аномалии), EscalationCycle (циклы в маршрутах эскалации), PriorityContradiction (противоречия приоритетов).
Принцип «один мутант — один ожидаемый отказ»: Главное правило фабрики мутаций. Один мутатор должен вносить только один дефект, чтобы при падении теста можно было точно локализовать причину и связать её с конкретным правилом.
Практические упражнения: Название: Запуск генерации мутаций и проверка детерминизма
Проблема: Необходимо перейти в каталог примера и запустить скрипт генерации мутаций с использованием операторов Nullify, FutureTime, EscalationCycle, PriorityContradiction и фиксированным seed 20260517. Требуется убедиться, что генератор является детерминированным.
Решение: 1. Откройте терминал и выполните: cd book2/examples/stress-mutator.
- Запустите генератор: python3 scripts/mutate_specs.py --base base/base_spec.json --seed 20260517 --operators Nullify,FutureTime,EscalationCycle,PriorityContradiction --out out/mutations.
- Повторите команду из шага 2.
- Сравните файлы манифеста: diff out/mutations/manifest.json manifest.example.json.
Ожидание: 0 строк различий, порядок mutation_id совпадает при каждом запуске.
Сложность: beginner
Название: Расчет вектора иммунитета валидатора
Проблема: Используя ранее сгенерированные мутации, запустите фейковый валидатор и скрипт расчета метрики иммунитета. Проанализируйте полученные значения и сделайте вывод о готовности контура.
Решение: 1. Запустите валидатор: python3 scripts/fake_validator.py --mutations out/mutations --out out/validator_results.json.
- Запустите расчет метрик: python3 scripts/immunity_score.py --validator-results out/validator_results.json --expected expected/expected_failures.json.
- Проверьте, чтобы значения соответствовали порогам: strict_reject_rate >= 0.98, depth_of_diagnostics >= 3, recovery_time_p95_ms <= 1200.
Сложность: intermediate
Название: Формирование ревьюируемого следа (Capstone)
Проблема: На основе проведенного дымового тестирования (практические упражнения 1 и 2) сформируйте минимальный фрагмент отчета для файла capstone/validation.md.
Решение: Создайте или откройте capstone/validation.md и добавьте блок, содержащий seed, список операторов, вычисленные три метрики иммунитета и итоговый вердикт (verdict: PASS/FAIL). Не коммитьте сам каталог out/mutations — источником истины должна быть воспроизводимая команда.
Сложность: intermediate
Кейсы: Название: Валидация инцидента appointment_latency_spike
Сценарий: Рассматривается production-инцидент с резким ростом задержек (appointment_latency_spike). Согласно спецификации, SLA составляет 10 минут, а маршрут эскалации идет от appointments_oncall к sre_lead. Базовый спецификатор содержит корректные данные для этого кейса.
Задача: Необходимо убедиться, что валидатор не пропустит ситуацию, когда поле severity становится пустым. Если пустое поле протечет в систему, оно может искажать расчет SLA и привести к ложному выбору владельца инцидента, что критично для пропускной способности дежурных инженеров.
Решение: Применяется оператор мутации Nullify к полю severity. Ожидается, что валидатор обнаружит дефект на этапе Given:incident_received и выдаст код EMPTY_REQUIRED_FIELD. Конвейер должен быть принудительно остановлен перед шагом When:evaluate_sla_window. Результат привязывается к правилу JSON Schema: severity.minLength.
Результат: Валидатор успешно остановил обработку до вычисления SLA. В SDD зафиксирована цепочка доказательств: mutation_id, различие в спецификации (diff: 'P1' -> ''), код диагностики и стек маршрутизации. Доказано, что валидатор обеспечивает «анатомическую диагностику».
Извлечённые уроки: Временные аномалии и пустые поля следует проверять до начала маршрутизации и вычислений SLA.
Принцип «один мутант — один ожидаемый отказ» критичен для локализации проблемы без ручной отладки.
Связанные концепции: Оператор Nullify
Формат Given/When/Then
strict_reject_rate
Название: Обнаружение цикла эскалации (cdn_error_budget_burn)
Сценарий: Анализируется инцидент с ошибкой бюджета горения (cdn_error_budget_burn). Владелец edge_oncall передает P1 инцидент команде traffic_sre.
Задача: С помощью оператора EscalationCycle в граф эскалации внедряется обратное ребро (traffic_sre → edge_oncall). JSON Schema проверяет форму данных хорошо, но не всегда способна выразить топологическое поведение маршрута. Необходимо проверить, не уйдет ли исполнительный контур в бесконечное переопределение владельца.
Решение: Валидатор строит ориентированный граф владельцев и запускает поиск в глубину (DFS) с состояниями white/gray/black. При обнаружении gray-узла возвращается ошибка CYCLE_ESCALATION с указанием минимального цикла. Отказ привязывается к шагу When:route_escalation.
Результат: Валидатор обнаружил цикл до исполнительной фазы и остановил процесс. Отчет показал четкий маршрут падения: schema.normalize -> step.when.prepare -> graph.build -> graph.detect_cycle -> halt.
Извлечённые уроки: Диагностика топологических циклов требует отдельного графового прохода внутри валидатора.
Каждый мутант должен быть привязан к конкретному правилу (например, $defs.escalation_graph.no_cycles), чтобы диагноз не был слишком общим.
Связанные концепции: Оператор EscalationCycle
Графовые проходы (DFS)
depth_of_diagnostics
Советы по изучению: Всегда проверяйте детерминизм: запускайте генератор мутаций дважды с одинаковым seed и сравнивайте файлы. Один прогон без проверки — это случайный шум, а не надежная метрика.
Обратите внимание на классы вырожденных сценариев (Пустые поля, Временные аномалии, Циклы эскалации, Рекурсивные зависимости). Разработчики часто забывают про обратные ребра в графах.
При изучении метрики иммунитета всегда рассматривайте ее как вектор. Если strict_reject_rate растет, а depth_of_diagnostics падает, ваш контур стал строже, но «слепее» (инженер не поймет, как исправить инцидент).
Запомните правило: Каталог out/ не коммитится в Git. Храните в репозитории только seed, операторы и сводные метрики.
Дополнительные ресурсы: Runnable example: book2/examples/stress-mutator/README.md — рабочие скрипты на Python для локального запуска фабрики мутаций и расчета иммунитета.
Part 09 feature validation: ../book/part-09-feature-validation.md — дисциплина фактов проверки, без которой мутации спецификаций теряют смысл.
Part 20 sdd antipatterns: ../book/part-20-sdd-antipatterns.md — каталог классических ошибок процесса, на основе которого строятся операторы мутации.
Резюме: Мутационное тестирование спецификаций превращает проверку валидатора в управляемый инженерный цикл. Используя фабрику мутаций, вы целенаправленно создаете вырожденные сценарии (пустые поля, циклы, ошибки времени) и проверяете, что валидатор ловит их на правильном шаге Given/When/Then. Вычисление векторной метрики иммунитета (strict_reject_rate, depth_of_diagnostics, recovery_time) позволяет настроить CI-шлюз, который не пропустит регрессию и защитит систему от токсичных требований и каскадных отказов.