Использование Mock-тестирования при интеграции с внешними системами
У нас в RNDSOFT довольно часто случается ситуация: при разработке приложения специалистам нужно взаимодействовать с внешними веб-сервисами или сторонними API. А когда такие взаимодействия несут потенциально опасные действия, хотелось бы как-то защититься и разрабатывать в некой безопасной среде.
Как бэкенд разработчик я могу воспользоваться mock-тестированием, это когда реальные объекты заменяются на контролируемые имитации.
Например, в ruby, используя gem webmock, я могу перехватить реальный HTTP запрос от моего приложения и имитировать нужный мне ответ.
Или с помощью gem vcr один раз записать HTTP запросы и ответы в файлы (кассеты) и в дальнейшем проигрывать эти кассеты вместо реальных запросов
В принципе, порог вхождения в такие инструменты не слишком большой, и их в обычных случаях хватает, чтобы не испытывать серьезных проблем в локальном окружении разработчика.
А теперь представим, что вы QA специалист, и в некоторых случаях нужно изолировать тестируемый код от внешних зависимостей, ведь они могут замедлить или усложнить тестирование.
Скорей всего, вы не можете легко получить контроль над сторонними API, чтобы воспроизвести нужные сценарии. Конечно, некоторые сервисы предоставляют тестовое окружение, и тогда это может быть выходом из ситуации. А если нет такого тестового окружения или оно не предоставляет вам необходимую гибкость в реализации сценариев тестирования? Например, для проверки поведения системы нужно протестировать сценарии с ошибками или недоступностью компонентов.
На помощь нам тоже приходит Mock-тестирование, но только реализовывается оно иначе, т.к. у тестировщика меньше возможностей вмешиваться в работу тестируемого кода.
Необходимо поднять mock-сервер, который будет имитировать ответы внешнего API и настроить тестируемое приложение таким образом, чтобы оно обращалось к mock-серверу вместо реального. Обычно все URL для внешних API выносятся в переменные окружения у контейнера, тогда им легко управлять.
В некоторых случаях можно организовать обратный прокси, чтобы имитировать только часть запросов, а остальные перенаправлять на внешнее API.
В интернете есть большое количество инструментов для mock-тестирования, принцип работы у них следующий:
- Создаете ваше Mock API, разница в том, как это сделано:
- Можно сгенерировать на основе OpenAPI Specification.
- Через графический интерфейс создать шаблоны запросов и ответов.
- Создать шаблоны, используя интерфейс управления на основе REST API.
- Записать шаблоны на основе реальных запросов и отредактировать.
- Развернуть Mock-сервер локально или в некотором окружении, некоторые инструменты предлагают платные облака для развертывания mock-серверов.
- Далее нужно реализовать у вашего приложения возможность конфигурировать адреса внешних сервисов и перенаправить запросы на mock-сервер.
- Используя возможности управления mock-сервером, проводить тестирования различных сценариев.
Вот кратко про некоторые из инструментов для mock-тестирования:
- Postman - в основном используется для API тестирования, но у него есть возможность поднять mock-сервер, хорошо подходит для разовых mock сценариев тестирования.
- SwaggerHub - моки создаются на основе OpenAPI Specification, и есть возможность по документации сгенерировать код готового mock-сервера под разные микрофреймворки.
- CastleMock - поднимается через докер, есть панель управления, можно загрузить OpenAPI Specification.
- Mockoon - работает локально, есть удобный GUI, можно загрузить OpenAPI Specification, есть возможность настроить обратный прокси и создавать моки на основе логов.
- MockServer - можно поднять в докере, есть небольшая панель управления, основное управление осуществляется через REST API.
Это далеко не полный список и есть еще много других под разные стеки технологий!
Есть еще вариант написать свой mock-сервер, но думаю, это более долгий путь, который помимо времени разработчика может потребовать наличия соответствующих компетенций в разработке у тестировщика.
Мы в качестве решения взяли mockoon, из-за его особенностей он подходит под наши потребности. У него достаточно хорошая документация и мощный функционал.
Это бесплатное opensource кроссплатформенное приложение с графическим интерфейсом, есть версии для Linux, Windows и MacOS.
Наша инфраструктура позволяет перенаправлять запросы с тестового контура на внутренние ip-адреса сотрудников, что упрощает развертывание mock-сервера. Поднял локально, сделал перенаправление с тестируемого приложения на свой IP и выбранный порт, и можно работать!
Либо можно подготовить коллекцию и поднять mockoon в докере на удаленной машине:
$ docker run -d --mount type=bind,source=/data-file.json,target=/data,readonly -p 3000:3000 mockoon/cli:latest -d data -p 3000/
Есть возможность сохранять коллекции шаблонов в json-файле, причем в виде, адаптированном под git, т.е. каждое ключ-значение на отдельной строке, а не сплошным месивом. Это позволяет держать коллекции для mock-сервера в репозитории проекта, обновлять его по мере разработки и использования разных частей внешнего API.
Так же это позволяет на этапе разработки подготовить шаблоны запросов, которыми уже будет пользоваться тестировщик при прогоне разных сценариев.
Для подготовки шаблонов есть возможность импортировать файл с OpenAPI Specification или настроить обратный прокси и создать шаблоны на основе полученных логов запросов, сервер работает таким образом, что сначала ищет варианты ответа среди созданных шаблонов, а если не нашел, то уже идет реальный запрос к стороннему API.
В принципе, можно в рамках одной коллекции настроить отображение разных сценариев, есть возможность создавать последовательности ответов, динамический шаблон ответа, настраивать условия в зависимости от параметров.
Заключение
Mock-тестирование позволяет разорвать зависимость от внешнего сервиса при разработке и тестировании. Что может быть необходимо в различных ситуациях, например, исключить потенциально опасные действия, протестировать негативные сценарии, разработать и протестировать фичу, когда внешний сервис еще не введен в эксплуатацию.
Но надо сказать, что у данной технологии есть и недостатки. Шаблоны могут недостаточно полно имитировать поведение реальной системы. Поэтому вы можете не найти некоторые ошибки, которые возникают при реальном использовании системы.
А неправильно настроенные шаблоны могут выдавать ложные результаты и, соответственно, приведут к ошибкам в процессе разработки.
Несмотря на недостатки, это быстрый и дешевый метод протестировать различные сценарии поведения вашей системы, а на этапе разработки подготовить коллекции и поделиться с командой и тем самым снизить потенциальные временные затраты на поддержку зависимости от внешнего сервиса.