ТестированиеАвтоматизация тестированияИнженер по автоматизации тестирования

Практическая ситуация: сервис должен корректно переживать недоступность критичной зависимости. Как автомати...

Практическая ситуация: сервис должен корректно переживать недоступность критичной зависимости. Как автоматизировать проверку этого поведения без ожидания реального сбоя?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

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

Исторический контекст

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

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

Постановка проблемы

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

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

Подробное решение

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

Полезно проверять несколько разных моделей поведения:

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

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

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

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

Ситуация из практики

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

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

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

Что кандидаты часто упускают

  1. Чем инъекция отказов отличается от подмены зависимости имитацией?

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

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

  1. Как проверить, что повторные попытки не создают дублирующий побочный эффект?

Нужно разделить повтор запроса и повтор операции. Тест должен внедрить отказ на определённом шаге, затем проверить количество фактически созданных сущностей или операций, а не только итоговый HTTP-статус.

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

  1. Какие сценарии отказов следует включать в обязательный CI-гейт?

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

Случайные массовые эксперименты, длительные сетевые нарушения и проверки поведения всей системы обычно лучше запускать отдельно. Компромисс заключается в балансе между ранним обнаружением критичного дефекта и скоростью, воспроизводимостью и стабильностью основного CI-прогона.