Мы отказались от устаревших статичных данных в автотестах и создали систему динамической генерации тестовых данных. Теперь каждое тестирование отражает реальное поведение пользователей, и именно это сделало его надежнее.
Когда тесты стали слишком идеальными
Через три года регулярных прогонов автотестов на крупном продукте мы заметили странность: тесты проходили подозрительно гладко. Ошибок почти не было, но и реальность они отражали все меньше.
Причина оказалась в самом фундаменте: автотесты опирались на статичные, «зашитые» данные, созданные еще при первом покрытии кода. Они были разработаны более трех лет назад и для скорости были объявлены в виде констант непосредственно перед кодом теста.
Эти статичные данные когда-то ускорили старт - позволили быстро покрыть систему тестами и отлавливать баги на ранних этапах. Постепенно по мере их устаревания мы столкнулись с тем, что:
- одинаковые значения вызывали конфликты при повторных запусках
- тесты перестали моделировать реальные сценарии
- любое изменение продукта требовало ручных правок в сотнях файлов
Мы поняли, что пришло время не просто «обновить данные», ведь это будет временная мера, а полностью переосмыслить подход.
Смена парадигмы
Возникла идея создавать тестовые данные «на лету», чтобы данные всегда были уникальны, и не привязывались к какому-то временному промежутку. Мы разработали систему динамической генерации данных, которая формирует входные данные непосредственно перед каждым прогоном тестов.
Основные принципы:
- Централизованный генератор данных
Это набор классов, отвечающих за создание валидных данных в нужном формате. Каждый класс знает правила формирования полей и автоматически генерирует значения, соответствующие бизнес-логике. Благодаря централизованности мы можем легко вносить изменения - корректируется только генератор, а не каждый тест отдельно.
- Строгие контракты и интерфейсы-шаблоны
Для каждого типа данных создается шаблон в виде интерфейса. Он определяет структуру и типизацию будущего JSON-объекта. Такой контракт гарантирует единообразие и предсказуемость данных, снижает количество ошибок при интеграции и упрощает сопровождение.
Требуемый шаблон создается в виде интерфейса
Затем создается функция-генератор, который на основании данных формирует json
- Гибкость сценариев
При запуске теста можно передавать параметры - часть данных задается вручную, а часть формируется автоматически. Это позволяет моделировать различные сценарии: от полностью случайных данных до строго контролируемых комбинаций. Так каждый тест может быть уникальным, но при этом полностью воспроизводимым.
Шаблон заранее корректно сформирован, и содержит вместо данных параметры, которые и будут подставляться
- Универсальный формат
Все данные формируются в формате JSON, что упрощает отладку, логирование и интеграцию с другими системами.
Итоговый файл для загрузки в систему
Автотесты перестали зависеть от артефактов прошлых лет и начали адаптироваться под каждый новый релиз.
Как это изменило тестирование
1. Повысилась надежность
Каждый прогон теперь уникален - исчез «синдром пестицида», когда тесты перестают находить ошибки в знакомых сценариях. Более того, случайно сгенерированные данные уже трижды помогли выявить критические баги, которые раньше мы бы не смогли отловить.
2. Ускорились процессы
QA-команда получила инструмент, который позволяет мгновенно генерировать нужные данные без ручной подготовки. Время на поддержку и актуализацию тестов сократилось примерно в 10 раз. Теперь изменения вносятся в одном месте, а не в сотнях файлов.
3. Снизилась стоимость тестирования
Все правки теперь централизованы: достаточно обновить генератор, а новые данные автоматически применяются во всех тестах. Это уменьшило трудозатраты и позволило тратить на актуализацию регресс-тестов всего пару часов при изменении бизнес-логики.
4. Тесты стали ближе к реальности
Данные отражают реальные пользовательские сценарии и непредсказуемость. Это повысило точность и ценность каждого тестового прогона.
5. Решение масштабируется
Генератор данных легко расширять. При появлении новых требований не нужно переписывать тесты, а достаточно добавить новый генератор или параметр.
В итоге мы сделали тесты чуть сложнее, чтобы продукт был надежнее.
Мы сделали автотесты «неудобными» - и именно в этом их смысл. Теперь они реагируют на изменения, проверяют реальные сценарии и помогают находить ошибки до того, как их замечает пользователь.