Генерация синтетических тестовых данных: подходы и реализация

Тестовые окружения собираются неделями, а данные из рабочего контура нельзя отдавать в разработку. Мы настраиваем генерацию синтетических тестовых данных под ключ: воспроизводимые наборы под каждый сценарий, без ручной подготовки и рисков утечки. Срок сборки окружений сокращается в разы.
Часто задаваемые вопросы

Что ломается без синтетических тестовых данных

Тестовый контур обычно наполняют выгрузкой из боевой базы — срезом на пару тысяч записей, снятым давно и с тех пор не менявшимся. Проверки на нём зелёные, а в проде падает сценарий, которого в срезе не было: заказ с двумя валютами, отмена после частичного возврата, слияние двух аккаунтов.

Дефицит тестовых наборов сильнее всего бьёт по редким состояниям. Их доля в реальных данных — доли процента, в выборку они не попадают, и нестабильные проверки годами не видят ни гонку при параллельном списании, ни разъезд часовых поясов, ни половину веток обработки отказов внешнего сервиса.

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

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

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

Что даёт генерация: измеримые эффекты

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

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

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

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

Сравнение подходов к синтетическим данным

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

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

Вариант Когда подходит Ограничения
Шаблоны и правила Массовые валидные по схеме записи: нагрузочные прогоны, проверка миграций, наполнение стендов Поля генерируются независимо, корреляции между ними прописываются вручную; редкие сочетания почти не встречаются
Генеративные модели Реалистичные распределения и аномалии: обучение моделей, тесты на редких сценариях Нужна репрезентативная выборка; риск переноса персональных данных; результат нестабилен, отдельный кейс трудно воспроизвести
Комбинированный подход И масштаб, и реализм: правила держат каркас, ключи и связи, модель добавляет вариативность Нужен контракт между слоями и валидация каждого шага, иначе сбой одного слоя маскируется другим

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

Как строится генерация: этапы инженерной работы

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

Этапы внедрения

  1. Инвентаризация источников. Фиксируем системы, форматы выгрузок, объёмы, места хранения персональных данных и правила их обезличивания.
  2. Профилирование данных и связей. Считаем распределения, кардинальность полей, доли пропусков, корреляции и правила ссылочной целостности — без этого генератор штампует «заказы без клиентов».
  3. Настройка правил генерации. Задаём типы и диапазоны, справочники, бизнес-инварианты вроде сходимости итогов, отдельные сценарии редких и граничных сочетаний.
  4. Сборка генератора. Настраиваем режимы: снимок структуры, набор в нужном объёме, воспроизводимость по фиксированному зерну — упавшую проверку разбираем на том же наборе.
  5. Приёмка наборов. Сверяем метрики с исходными и прогоняем проверки: они должны падать на подложенных дефектах и не срабатывать на чистых данных.
  6. Передача регламента обновления. Описываем, как менять правила при изменении схемы, где лежат конфигурации и как версионируются наборы.

Такой порядок делает генерацию повторяемой: правка схемы источника не ломает проверки незаметно.

Что передаём на руки: артефакты и регламенты

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

  • Конфигурации генерации: правила распределений, ограничения по полям, справочники значений и начальные параметры, при которых набор собирается один в один.
  • Схема связей таблиц: карта внешних ключей и порядок генерации, при котором дочерние записи получают согласованные родительские.
  • Правила доступа: каким командам и сервисам разрешено читать наборы, кто вправе запускать генерацию и менять её параметры.
  • Документация по наборам: состав сущностей, объём, распределение ключевых полей и перечень сценариев, которые набор покрывает.
  • Регламент обновления и повторного запуска: что становится поводом для пересборки, какие проверки прогоняются и по какому критерию набор принимается в работу.
  • Скрипты контроля целостности: проверка ссылок, дублей и выхода значений за допустимые границы — выполняются до выдачи данных командам.
  • Отчёт о покрытии: какие ветки логики и классы отказов закрыты сгенерированными сценариями, а какие осознанно оставлены на реальных данных.

Через несколько недель после сдачи пересборку под новую схему вы запускаете сами — без возврата к нам за каждым изменением.

Кейс: сократили ручную подготовку окружений

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

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

Управляемость оказалась важнее объёма: профиль генерации описывается декларативно — доли аномалий, распределения по категориям, редкие состояния. Новый сценарий добавляется правкой профиля, а не переписыванием генератора, и набор собирается под конкретную проверку.

Что изменилось

Сборка набора занимает минуты вместо пяти дней, доля покрытых граничных сценариев выросла с 40% до 95%, ручные правки данных ушли из процесса выпуска. Инженеры больше не ждут окружение: чистая база поднимается одной командой.

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

Что делать, если обезличивание уже внедрено

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

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

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

Миграция идёт постепенно. Сначала генерация закрывает то, чего копия не даёт: объём для нагрузочных прогонов, граничные случаи, редкие классы. Эталонные наборы для регрессии остаются на обезличенных данных, и процесс не ломается — меняется только источник части наборов.

Контроль обязателен: сверяем профили распределений и правила ссылочной целостности между обезличенным и сгенерированным наборами, чтобы не появлялись невозможные комбинации. Разделение простое: обезличивание отвечает на вопрос «не утекли ли данные», генерация — на вопрос «хватает ли данных и покрыты ли редкие классы».

Технические сомнения: утечки и воспроизводимость

Инженеры задают одни и те же вопросы до старта: не попадёт ли в набор реальная выгрузка, чем подтверждается его качество и что будет, когда схема поменяется. Ниже — ответы без общих слов.

Реальные данные могут попасть в синтетику?

Генератор работает на описании схемы, распределений и правил связности, а не на выгрузке из боевого контура. Реальный срез берём только для сверки распределений — обезличенным и на этапе анализа, в готовый набор он не попадает.

Как убедиться, что набор качественный?

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

Набор воспроизводим на другой машине?

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

Что происходит после изменения схемы?

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

Набор выдержит нагрузочные проверки?

Объём задаётся отдельно от правдоподобия: генератор масштабируется до нужного числа записей, сохраняя связи между сущностями. Так поведение системы проверяется на объёмах, которых в рабочем контуре нет.

Обсудим задачу и вернёмся с оценкой и планом

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

Со своей стороны возвращаем:

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

Опишите задачу и текущие ограничения — вернёмся с оценкой и планом работ, а пилотный набор соберём на ваших данных, чтобы подход подтвердился до начала основного этапа.

Направления AI-разработки

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    816
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1141