Интеграционный тест иногда падает только на случайных тестовых данных. Какой механизм подготовки данных позволит воспроизвести тот же прогон?
Используйте управляемую случайность: генерируйте данные псевдослучайно с сохранённым начальным значением — seed. При падении тест должен записать seed и параметры генерации, чтобы повторный запуск создал тот же набор данных.
Фиксированные наборы данных хорошо обнаруживают заранее известные сценарии, но ограниченно покрывают комбинации значений. Случайная генерация расширяет покрытие, однако без воспроизводимости превращает ошибку в трудноисследуемый эпизод.
Подход с seed сохраняет преимущество случайного перебора и одновременно делает результат повторяемым. Он особенно полезен для интеграционных проверок, где ошибка может зависеть от сочетания полей, порядка операций или граничных значений.
Если тест использует непредсказуемые данные и не сохраняет параметры генерации, следующий запуск может не воспроизвести сбой. Команда видит нестабильный тест, но не может надёжно понять, какие входные значения привели к ошибке.
Одного seed недостаточно, если результат зависит от текущего времени, случайного порядка выполнения, состояния общей базы или версии генератора. В таком случае необходимо фиксировать и контролировать все существенные источники изменчивости.
Перед генерацией данных тест выбирает seed либо получает его из параметров запуска. Генератор использует этот seed для создания значений, а тест записывает seed, версию генератора, параметры сценария и, при необходимости, итоговые входные данные в отчёт.
При воспроизведении запускают тот же сценарий с тем же seed. Для параллельных тестов каждому сценарию следует выдавать независимый seed или отдельный генератор, чтобы порядок обращений к общему генератору не менял данные.
Данные должны оставаться валидными для предметной области, но включать граничные и редкие комбинации. При этом случайная генерация не заменяет явные проверки известных бизнес-правил: критичные случаи лучше закреплять отдельными детерминированными тестами.
Практические ограничения связаны с изменением алгоритма генерации. После обновления библиотеки или самого генератора тот же seed может дать другой набор данных, поэтому для расследования важно сохранять версию генератора и не считать seed вечным идентификатором входа.
Интеграционный тест расчёта заказа создавал случайное количество позиций, скидки и способы доставки. Иногда сервер возвращал неверную итоговую сумму, но повторный запуск проходил, поскольку набор данных уже был другим.
Рассматривались три варианта. Полностью фиксированные фикстуры упрощали диагностику, но плохо покрывали комбинации; повторять тест много раз без сохранения входа было дёшево, но не гарантировало воспроизведение; сохранение seed добавляло небольшую сложность, зато позволяло точно повторить сбой.
Выбрали третий вариант: seed выводился в отчёт и сохранялся вместе с параметрами генерации. После этого дефект воспроизводился локально на том же наборе данных, а исправление проверялось повторным запуском с исходным seed.
Не всегда. Нужно сохранить также версию генератора, параметры сценария, настройки локали и часового пояса, а при зависимости от внешнего состояния — версии или идентификаторы этого состояния. Иначе одинаковый seed может привести к другим фактическим входам.
Это рискованно. Параллельный запуск или изменение порядка тестов меняет последовательность обращений к генератору, поэтому данные конкретного теста становятся нестабильными. Лучше использовать независимый генератор на тест или на сценарий с производным seed.
Нет. Случайные данные полезны для поиска неизвестных комбинаций, но ключевые бизнес-сценарии должны быть явно заданы и легко читаемы. Оптимален смешанный подход: детерминированные тесты для обязательных правил и воспроизводимая случайная генерация для расширения покрытия.