Четыре способа для проверки не существовать
| Как выглядит | Что видит человек | Что происходит на деле |
|---|---|---|
| Написана, но не вызывается ниоткуда | файл на месте, код осмысленный | не запускается никогда; таких нашлось шесть |
| Вызывается, но берут одну вспомогательную функцию | модуль импортируется, значит «используется» | содержательная часть не выполняется нигде |
| Единственный вызыватель — сам осиротевший инструмент | вызов в коде есть | цепочка обрывается на шаг выше |
| Зарегистрирована в настройках, файла нет в репозитории | в конфигурации прописана | на любой свежей копии молча не запускается |
Ни один из четырёх случаев не даёт ошибки. Ничего не падает, лог чистый, отчёт зелёный. Отсутствие проверки выглядит точно так же, как проверка, которая ничего не нашла, — и это единственная причина, по которой такие дыры живут годами. Поиск «кто кого вызывает» по всему дереву занимает час и находит их все сразу.
Хуже всего третий и четвёртый случаи, потому что в них есть видимость вызова. Строка вызова существует, поиск по коду её находит, и проверяющий закрывает вопрос. Смотреть надо не на наличие вызова, а на то, доходит ли до него управление в реальном прогоне.
Документы закрепляют то, чего нет
Отдельный механизм, продлевающий жизнь мёртвой проверке, — собственная документация. Шаг, описанный в тридцати файлах как ручной, читается как существующая практика: раз столько раз написано, значит кто-то так и делает. Проверить это можно только прогоном, а не чтением.
Две поломки, и вторая маскируется первой
Самый коварный случай попался в фоновом мониторе. Расписание — каждые три часа. Все восемь последних прогонов красные, и падают они раньше — по другой, посторонней причине. Разбор показал, что за первой поломкой стоит вторая: запускаемого файла нет в репозитории, и до него исполнение просто не доходит.
Когда рванёт. Вторая поломка вылезет ровно в тот момент, когда первую починят и решат, что монитор снова работает. Сейчас красный статус объясняется знакомой причиной, и объяснённый красный перестаёт тревожить. Правило простое: чиня падающий прогон, доводите его до зелёного, а не до «падает по понятной причине». Пока прогон не дошёл до конца, вы не знаете, сколько поломок стоит в очереди.
Родственный дефект — обработчик, зарегистрированный в настройках, но не попавший в репозиторий. На машине автора он работал; на любой свежей копии и в любой рабочей ветке он молча не запускался. Проверка при этом считалась внедрённой и обязательной.
Класс, который ловится только автоматической проверкой
Ради чего вообще держать живые гарды, хорошо показывает один класс дефекта: инструмент подписывается твоим именем в чужой инфраструктуре. Скрипт ходит во внешний сервис от лица клиента, но в идентификаторе запроса остаётся что-то ваше — домен, почта, внутреннее имя. Работает всё исправно, ошибок нет, в логах у себя не видно ничего. Видно снаружи — и не вам.
Глазами такое не ловится: строка с идентификатором пишется один раз при отладке и потом не читается никем. Лечится ровно одним способом — автоматической проверкой, которая падает, если в исходящем запросе встречается любой ваш собственный маркер. Список маркеров заводится один раз, проверка ставится в тот же прогон, что и остальные тесты.
Что забрать себе
- Пройдите свои проверки поиском «кто меня вызывает». Час работы; результат обычно неприятный и всегда полезный.
- Импорт модуля не равен запуску проверки. Смотрите, какая именно функция берётся: вспомогательная часть может использоваться, а содержательная — нет.
- Красный прогон доводите до зелёного. «Падает по известной причине» скрывает следующую поломку и превращает монитор в декорацию.
- Всё, что зарегистрировано в настройках, должно лежать в репозитории. Иначе проверка работает на одной машине и нигде больше.
- Границы описывайте запретом, а не памятью. Проверка «наружу не уходит ничего нашего» дешевле, чем помнить про каждый идентификатор в каждом скрипте.