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