Наш сборщик видеороликов упал в первую же ночь, а 17 тестов молчали
Что случилось за один прогон
Мы запустили автоматический конвейер, который каждую ночь собирает короткие видеоролики по свежим статьям. До этого — несколько недель тестов на синтетических данных. Первый живой прогон сломался дважды, и оба сбоя были скрыты от автоматических проверок. Не потому что их было мало — их было 17. Потому что они проверяли не то, что нужно.
Именно это задело сильнее всего: не сам факт поломки, а то, что система выглядела готовой. Тесты проходили. Файлы были на месте. Функции отвечали. Прогон всё равно упал на первой строке.
Первый сбой: функция есть, но зовут её неправильно
Прогон упал на первой строке — функция ждала список дат, а ей передали одно целое число. Функция существовала, принимала нужные данные, и автопроверки это фиксировали. Только они проверяли наличие функции, а не то, как её зовут в реальных условиях. Разница небольшая на словах и полная остановка на практике.
Пятнадцать минут на диагностику, одна строка в исправлении. Новая проверка теперь зовёт всю связку целиком: берёт даты тем же сборщиком, который их строит в рабочем режиме, получает список адресов статей, проверяет, что он непустой. Нет смысла проверять отдельные шестерёнки, если механизм работает как единое целое.
Я понял, что писал проверки-свидетели, а не проверки-участники. Свидетель говорит «функция есть». Участник говорит «я позвал функцию так, как её зовёт рабочий код, и получил ответ».
Второй сбой: текст вышел за плашку
В жёлтой капсуле с призывом к действию кегль был зафиксирован постоянным числом — 46 единиц. Пока призывы были короткими, всё помещалось. Длинный текст вылез за правый край и обрезался прямо на кадре. Система проверки видео это не поймала: она замеряет размер файла, яркость, контраст, пропорции. Что текст вышел за свою плашку — не видит. Нашли глазами.
Это не ошибка в логике проверки. Это граница того, что вообще можно выразить числом. Яркость — можно. Пропорции — можно. «Текст выглядит нормально» — нет. Некоторые вещи остаются за человеческим взглядом навсегда, и принять это — уже половина дела.
Почему 17 проверок не поймали ни то, ни другое
До первого живого прогона у нас было 17 автоматических проверок. Они фиксировали, существуют ли нужные функции, открываются ли рабочие папки, отвечает ли языковая модель, правильные ли пропорции у ролика. Каждая делала своё дело честно. Проблема не в количестве — проблема в уровне, на котором задаётся вопрос.
«Функция существует» и «функцию можно правильно позвать с реальными данными» — это два разных утверждения. Мы писали первые, думая, что закрываем вторые. На синтетике разница незаметна. На живом прогоне разница — это или готовый ролик, или сообщение об ошибке.
Скорее всего, поймать это раньше было нельзя: такие вещи видны только тогда, когда система впервые работает с настоящими данными в настоящих условиях. Но теперь у меня есть конкретное правило: каждая критическая связка должна быть проверена сквозным вызовом, а не набором проверок её частей.
Что изменилось после
После починки — 20 автопроверок у сборщика, 17 у прогона дня. Кегль призыва теперь подбирается динамически: начинает с 46 единиц, уменьшается до 26, пока текст не уместится в отведённую плашку. Самый длинный из всех заведённых призывов входит в автопроверку — если не вмещается даже при минимальном кегле, тест падает ещё до запуска.
Публикация вынесена в отдельную функцию с четырьмя собственными проверками. Отказ, молчание и любой сбой оставляют ролик неопубликованным. «Скрипт не смог» — тоже ответ, его надо уметь возвращать.
Первый прогон после исправлений: ролик 9,0 секунды, 1080 на 1920, уровень музыки минус 26 децибел. Кадр просмотрен глазами.
Что можно проверить у себя прямо сейчас
Возьмите любую автоматическую проверку в вашем проекте. Не весь набор сразу — одну, самую важную с вашей точки зрения. Прочитайте, что именно она делает. Не как называется, а что происходит внутри: что запускается, что передаётся, что проверяется в ответе. Потом ответьте себе честно на три вопроса.
Первый — проверка фиксирует, что функция существует, или что её можно позвать с реальными данными и получить ответ?
Второй — есть ли хоть одна проверка, которая прогоняет всю цепочку от входа до выхода на живом примере, а не на заготовленной константе?
Третий — какие проверки у вас автоматизированы только потому что их удобнее автоматизировать, хотя на деле их нужно смотреть глазами?
У нас после разбора осталась одна открытая точка: система по-прежнему не замеряет, не вышел ли текст за плашку у нового элемента кадра. Подбор кегля делает этот случай практически невозможным — но «практически» и «точно» разные слова. Новый элемент снова придётся смотреть глазами.
Сколько таких точек вы найдёте у себя, если честно пройдёте по своей цепочке?
