Как заставить LLM генерировать реалистичные данные для тестов?

Как заставить LLM генерировать реалистичные данные для тестов?

Вступление

В предыдущем посте мы разобрали, как с помощью LLM можно генерировать тестовые данные, пригодные для работы QA.

Но что делать, если LLM генерирует "аккуратные" данные, а в продакшене встречаются опечатки, лишние пробелы, невалидные символы, устаревшие форматы или неожиданные значения? LLM не знает историю вашего приложения и особенностей бизнес-процессов без добавления дополнительного контекста. К тому же, передача реальных данных пользователей в модель может быть небезопасна и может нарушать требования закона о персональных данных.

Проблема

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

При этом реальные записи пользователей не должны передаваться в LLM. Сначала выявляется повторяющаяся аномалия, из нее удаляются персональные и конфиденциальные данные. Далее проблема описывается в абстрактном виде.

Вместо сохранения исходной записи пользователя фиксируется только ее абстрактная структура. Например: "user@example.com " — email содержит пробел в конце строки.

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

Вне зависимости от того, кем будет выполняться задача — мануальным тестировщиком или AQA, важно правильно подготовить сам процесс.

Еще больше материала про AI QA и тестирование AI-приложений в Telegram-канале ModernQA

Решение

Для этого необходимо проделать следующие шаги:

Шаг 1. Определить источники аномалий

Паттерны можно собирать из разных источников. Например, баги и инциденты в jira, обращения в поддержку, cбор логов и мониторингов или проблем при миграции данных.

Важно сохранять не исходную запись целиком, а причину проблемы и общую структуру.

Например, после импорта csv-файла в поле email иногда остаются лишние пробелы. В каталог стоит занести не конкретный email пользователя, а сам паттерн, что email может содержать пробел в конце строки после импорта.

Шаг 2. Описать паттерн в каталоге

Конкретный инструмент не так важен. Начать можно с Excel, Google Sheets или markdown-файла. Если каталог используется в автотестах, его удобнее хранить в git-репозитории в yaml, json или csv.

Главное, чтобы запись в каталоге отвечала на несколько вопросов:

  • что именно произошло;
  • где возникла аномалия;
  • откуда она появилась;
  • какой риск создает;
  • как ее воспроизвести на синтетических данных;
  • что должна сделать система;
  • как понять, что пример действительно соответствует паттерну.

Каталог может включать следующие поля:

  • ID паттерна — уникальный идентификатор паттерна. Пример: user_email_trailing_space
  • Сущность — объект, к которому относится проблема. Пример: User, Order, Payment, Profile
  • Поле / атрибут — поле или атрибут сущности, в котором возникает аномалия. Пример: email, phone, payment_id, status
  • Тип аномалии — категория проблемы. Пример: trailing_space, missing_reference, invalid_enum
  • Описание — что именно происходит. Пример: Значение email содержит пробел в конце строки
  • Источник — откуда появляется аномалия в продакшене. Пример: Ручной ввод, csv-импорт, legacy-миграция
  • Риск — какие проблемы может вызвать эта аномалия. Пример: Дубли пользователей, некорректный статус заказа
  • Что проверять — какие проверки нужно выполнить. Пример: Удаляются ли лишние пробелы, приводится ли значение к единому формату, и не создаются ли дубли
  • Условия появления — при каком контексте возникает аномалия. Пример: значение поступает через сsv-импорт без предварительной очистки.
  • Ожидаемое поведение — как система должна реагировать на эту аномалию. Пример: Система должна удалять лишние пробелы до проверки уникальности и сохранения;
  • Правило генерации — как воспроизвести аномалию на синтетических данных. Пример: добавить к валидному email один или несколько пробелов
  • Правило проверки паттерна — как убедиться, что результат соответствует паттерну. Пример: строка заканчивается пробелом, а после rstrip() становится валидным email.
  • Пример — безопасный синтетический пример аномалии. Пример: "user@example.com "
  • Приоритет — степень важности аномалии. Пример: Highest, High, Medium, Low

Именно на этом этапе реальная проблема из продакшена превращается в безопасный тестовый паттерн. Без персональных данных, но с сохранением сути, риска и правила воспроизведения.

Шаг 3. Приоритизировать паттерны

Приоритет можно определять по нескольким факторам:

  • серьезность последствий;
  • частота появления;
  • влияние на критичные бизнес-сценарии;
  • сложность обнаружения проблемы до выхода в продакшен;
  • наличие существующего покрытия.

Например, пробел в необязательном комментарии и пробел в email имеют разный риск.

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

Шаг 4. Передать паттерн в LLM

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

В запросе к LLM полезно указать:

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

Например, вместо общего запроса лучше передать модели конкретный паттерн, как часть структурированного промпта:

"Роль: Ты QA-инженер, который помогает подготовить синтетические тестовые данные на основе описанного паттерна аномалии.

Задача: Сгенерируй тестовые варианты для проверки обработки email после csv-импорта.

Контекст: В системе есть сущность User. Пользователи могут импортироваться из csv-файла. В продакшене встречалась аномалия: после импорта в поле email иногда остается пробел в конце строки.

Паттерн аномалии:

  • ID паттерна: user_email_trailing_space
  • Сущность: User
  • Поле / атрибут: email
  • Тип аномалии: trailing_space
  • Правило генерации: добавить к валидному email от одного до трех пробелов в конце строки
  • Риск: дубли пользователей, ошибки поиска или авторизации
  • Ожидаемое поведение: система удаляет лишние пробелы до проверки уникальности и сохранения

Ограничения:

  • не используй реальные персональные данные
  • используй только синтетические email
  • не добавляй другие аномалии, кроме пробела в конце строки
  • не используй невалидные домены, если это не требуется паттерном
  • каждый пример должен быть пригоден и для ручной проверки, и для параметризованного автотеста

Формат ответа:
Верни таблицу со столбцами:
1. ID тест-кейса
2. Входящий email
3. Аномалия
4. Что проверяем
5. Ожидаемое поведение
6. Использование в ручной проверке
7. Использование в автотестах

Критерии качества:

  • сгенерируй 10 вариантов
  • варианты должны отличаться друг от друга
  • в каждом варианте должна быть только одна целевая аномалия
  • ожидаемое поведение должно быть однозначным
  • не добавляй лишних пояснений вне таблицы

Таким образом LLM будет работать внутри понятных ограничений.

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

Шаг 5. Проверить результат генерации данных

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

LLM может:

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

Для каждого сгенерированного примера стоит проверить:

  • присутствует ли нужная аномалия;
  • нет ли дополнительных незапрошенных ошибок;
  • отсутствуют ли персональные данные;
  • можно ли определить ожидаемый результат;
  • остается ли запись пригодной для теста;
  • соответствует ли пример исходному паттерну из каталога.

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

Шаг 6. Связать паттерны с тестами

Паттерны должны обязательно работать. Из каждой внесенной аномалии должно быть понятно, где она проверяется, какой риск покрывает и используется ли она в регулярных проверках продукта.

Качественно заполенные паттерны можно использовать по-разному.

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

Для AQA этот же паттерн может стать основой для параметризованного автотеста или регрессионной проверки. Важно, чтобы автотест был связан с ID паттерна, а не просто использовал случайное “грязное” значение без объяснения, какой риск оно покрывает.

Такие данные можно использовать в:

  • ручных тест-кейсах;
  • чек-листах;
  • регрессионных проверках;
  • тестах миграций и импортов;
  • параметризованных автотестах;
  • проверках качества самих тестовых данных.

В каталоге можно отмечать:

  • покрыт ли паттерн ручным тестом;
  • существует ли автотест;
  • где находится проверка;
  • для каких окружений она применяется;
  • когда паттерн проверялся последний раз.

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

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

Так каталог становится общей базой знаний о реальных аномалиях и способах их воспроизведения через LLM.

Вывод

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

LLM хорошо масштабирует то, что уже понято и зафиксировано. Но такой каталог все равно нужно собирать самостоятельно.

Источники

1
1