Почти 3000 тестов держат наше расчётное ядро неизменным

Замороженное расчётное ядро означает, что цифра, показанная клиенту вчера, останется той же и сегодня. За это отвечают около 750 backend-тестов и 2100 frontend-тестов.

· 4 мин

Как почти 3000 тестов удерживают расчётное ядро TV Budgeting неизменным

Мы держим этот набор тестов ради одного свойства, которое плохо продаётся в буклете, но проявляется в работе каждый день: одинаковые входные данные должны давать одинаковый результат в любой версии инструмента. «Примерно так» здесь не вариант.

Почему в медиаматематике нет режима «примерно верно»

Медиарасчёт живёт долго и по пути переходит из рук в руки: тендер, затем контракт, затем пост-бай. Каждая передача превращает цифру в обязательство перед кем-то ещё — клиентом, сейлз-хаусом, финансовым отделом. У аналитического дашборда другой профиль риска: неверную цифру заметят и исправят на следующем обзоре.

Когда коэффициент незаметно меняется между двумя версиями, ущерб никогда не ограничивается одной ячейкой. Контрактная сумма перестаёт сходиться с обоснованием, под которое её утвердили, и спор начинается с худшего из возможных вопросов: какая версия считала правильно? Если логика нигде не зафиксирована, ответить не может никто в комнате.

Два слоя, где расчёт чаще всего ломается

Скидки сейлз-хауса — самый наглядный случай. Они перемножаются, а не складываются:

combined = 1 − ∏(1 − r)

Так, 20% и 10% дают 28%, а не 30%. Разница в два пункта кажется мелочью, пока её не умножить на бюджет кампании. Формула так и норовит схлопнуться в сложение — и обычно именно там это и происходит: в копии файла, который кто-то другой отредактировал, или в спешке перед отправкой. Тест фиксирует правило: сложение процентов вместо перемножения ломает сборку, а не всплывает на переговорах.

Второй слой тоньше, и вручную его почти невозможно проверить. Цикл «бюджет → порог скидки → бюджет» сходится через итерации: бюджет определяет порог, порог меняет бюджет, и так по кругу, пока пара не стабилизируется. Иногда значение колеблется между двумя соседними порогами и не оседает ни на одном. Тогда ядро берёт больший бюджет — консервативное решение для байера: лучше зарезервировать с запасом, чем обнаружить нехватку уже в ходе кампании. Всё это не видно в интерфейсе, а типовые случаи его вообще не затрагивают. Безобидный на вид рефакторинг ломает эту логику, и кто-то замечает это лишь кварталом позже, когда сравнивать уже не с чем.

Как выглядят сбои в этих двух слоях
Суммирование скидок — незаметно упрощается до сложения; ошибка растёт вместе с бюджетом; ловится юнит-тестом на формулу совокупной ставки.
Итерация порогов — правило разрешения колебаний теряется при рефакторинге; не видно в интерфейсе; ловится только тестом, который проверяет выбор большего бюджета при равенстве.

Значит ли «заморожено», что продукт перестаёт развиваться?

Нет. Заморожено — значит, что любое изменение результата осознанно, объяснимо и видно в тот же день, а не всплывает сюрпризом месяцы спустя. Мы выпускаем обновления непрерывно. Мы блокируем только числовые расхождения, просочившиеся как побочный эффект чьей-то несвязанной правки; каждое такое изменение проходит через явное решение.

Наш якорь — само ядро: одни и те же исходные данные дают один и тот же результат в любой сборке. При внедрении мы дополнительно сверяемся, ячейка за ячейкой, с моделью, с которой агентство приходит, чтобы переход не сломал историю, которую клиент уже согласовал, — этот барьер держится ниже 0,01%, проверяемое на каждой сборке, а не утверждённое один раз в начале внедрения. Если расхождение растёт, сборка не проходит. Данные Nielsen мы воспроизводим в тех значениях, в которых их получаем: расчётный слой не вправе подгонять входные цифры под себя.

Тесты как протокол, а не как QA

На практике эти тесты работают как протокол. Они хранят договорённости о математике в исполняемом виде — вне головы того, кто написал формулу, и вне комментария к ячейке, который в лучшем случае переживёт одну передачу файла. Воспроизводимость отличает инструмент от таблицы куда решительнее, чем интерфейс; подробнее об этом — в статье Альтернативы корпоративным платформам медиапланирования

.

Одна граница проговорена прямо: CPP внутри TV Budgeting — это плановый прокси, а не контрактная цена. Замороженное ядро гарантирует, что арифметика стабильна и воспроизводима. Оно не превращает прокси в доказательство реальной стоимости, экономии или ROI.

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

FAQ

Что на самом деле значит «замороженное расчётное ядро»?

То, что любое изменение вычисляемого результата должно быть осознанным, объяснимым и видимым в тот же день. Разработка продолжается — незаметный числовой дрейф нет.

Сколько тестов покрывает ядро?

Около 750 backend- и около 2100 frontend-проверок — почти 3000 в сумме, запускаются на каждой сборке.

Что происходит при переходе с модели, которой агентство уже пользуется?

Ниже 0,01% — это требование проверяется на каждой сборке, а не утверждается один раз при внедрении. Если расхождение растёт, сборка не проходит.

Почему тесты ловят петлю порогов скидки, а ручная проверка — нет?

Правило разрешения колебаний — брать больший бюджет, если значение мечется между двумя соседними порогами, — не видно в интерфейсе и не встречается в типовых случаях. Удерживает его на месте только проверка в тесте.

Посмотрите ядро в действии

Каждое описанное здесь правило работает внутри TV Budgeting — перемножение скидок, итерация порогов и один и тот же ответ при любом перезапуске.

Запросить демо →