Почему статичные моки убивают тестирование, и что мы с этим сделали

Час-пик для транспорта, финансовые хайлоады, антифрод — что у них общее? В этих системах стандартное нагрузочное тестирование не работает, потому что они падают из-за совпадения неожиданных сценариев одновременно.

Обложка: Почему статичные моки убивают тестирование, и что мы с этим сделали

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

В чём проблема статичных моков

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

Любой такой срез — это один конкретный сценарий: обычный будний день без аномалий. Удваиваешь нагрузку — получаешь тот же день в двойном объёме, а не новый сценарий. Что будет с данными транспортной системы, когда одновременно закроется станция метро, изменится маршрут нескольких автобусов и в той же зоне начнут продавать Лабубу? Каждый из этих случаев по отдельности некритичен, но если произойдут в один момент — система ляжет, потому что тесты ситуацию не предсказали.

Имитационное моделирование и модель швейцарского сыра

Нагрузочный тест отвечает на вопрос «выдержит ли система X запросов в секунду». Имитационное моделирование — на другой: «что случится с архитектурой, если несколько независимых факторов сойдутся в одной точке одновременно». Объяснить логику помогает модель швейцарского сыра: каждый слой защиты системы — кусок сыра с дырками. Одна дырка в одном слое не проблема, следующий слой её закроет, но если дырки в нескольких слоях выстроились в линию — получается сквозное отверстие.

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

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

Как мы собрали данные и построили систему

Чтобы покрыть максимум сценариев, выстроили систему из трёх источников данных. Все три источника работают в MLOps-пайплайне:

  1. Постоянный поток данных из реального мира. Наш пайплайн автоматически «дёргает» из продакшена свежие срезы данных и логи, мы специально ищем в проде резкие всплески нагрузки, нетипичное поведение пользователей, чтобы с ними экспериментировать.
  2. Обезличенные данные. Проблему с персональной информацией решили на уровне архитектуры: система создаёт для каждого пользователя профиль с UUID и привязывает к нему только неперсональные атрибуты — возраст, пол, поведенческие паттерны, но не хранит и не обрабатывает личные данные.
  3. ML-генерация экстремальных сценариев. ML-модель берёт реальные аномалии из прода и комбинирует их между собой — мы подкидываем ей свои гипотезы и элементы случайности, чтобы получить сценарии, которых в реальных данных ещё не было, но которые теоретически возможны.

Какие инструменты мы использовали

Весь пайплайн держится на шести инструментах.

  • Great Expectations описывает правила качества данных в виде обычных тестов. Если входящие данные нарушают хотя бы одно правило, система сигналит до того, как данные попадут в модель. Правила описывает QA — он решает, какие данные считать правильными для системы.
  • Evidently AI и NannyML следят за дрейфом — ситуацией, когда реальные данные начинают отличаться от тех, на которых обучалась модель. Инструменты постоянно сравнивают новые данные с эталонными, если ситуация критическая — QA в этот момент запускает переобучение.
  • DVC версионирует данные так же, как Git версионирует код: каждое изменение датасета фиксируется, и в любой момент можно вернуться к предыдущей версии или воспроизвести эксперимент.
  • MLflow фиксирует эксперименты: какие данные использовались, какие гиперпараметры были выставлены, какой результат получился — мы можем сравнивать запуски между собой и видеть, в какую сторону меняется качество.
  • Terraform и Ansible описывают инфраструктуру как код и гарантируют, что dev, staging и prod разворачиваются идентично.
  • Airflow управляет всем потоком задач, описывает зависимости между ними, следит за выполнением и фиксирует ошибки.

Как сделать также, пошаговый план

Это займёт у вас не один спринт, но вот как двигались мы:

  1. Написали скрипты для проверки качества данных, а не полезли сразу в модель. 
  2. Сложное автоматизировали после простого. Мы не пошли сразу в экстремальные ситуации, сначала обучали модель на простых сценариях. 
  3. QA подключили к архитектуре с самого начала. Он закладывает правила и логику реакций на разные типы данных. 
  4. Observability и reproducibility выстраивали параллельно с основным пайплайном: observability смотрел почему модель повела себя именно так, reproducibility решал проблему.
  5. И последнее — обновили роль QA. QA обязан участвовать в проектировании архитектуры с самого начала. Это senior-специалист, который заложил в систему правила и логику, как реагировать на разные типы данных.

Результат

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

Модуль генерации данных, который строили под этот проект, перенесли на бенчмарки и тестирование систем на деградацию производительности — сейчас он работает на нескольких проектах параллельно.