Автоматизированные тесты «все в одном» — автоматическая подготовка среды + выполнение тестов компонентов

Современные системы обычно зависят от стека программного обеспечения, такого как база данных, брокер сообщений и API внешних служб. Разработчикам необходимо установить это программное обеспечение на свой компьютер, чтобы запустить систему для разработки и тестирования. Однако установка и настройка среды для разработки — трудоемкая работа. Перед разработкой требуются усилия по настройке среды. Из-за зависимости от других программных компонентов тесты не могут быть полностью автоматизированы.

В этой статье я покажу вам, как запускать тесты компонентов/интеграции с настройкой среды с помощью Docker и Wiremock. Затем вы увидите, как автоматизировать весь процесс тестирования от подготовки среды до выполнения теста.

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

Система зависит от RabbitMQ, MongoDB и внешней службы клиентского API. На приведенной ниже диаграмме показаны компоненты, необходимые для того, чтобы система работала.

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

Использование Docker Container для локальной разработки

Настоятельно рекомендуется запускать необходимые программные компоненты в док-контейнерах. Благодаря мобильности технологии докеров программное обеспечение, такое как базы данных, можно использовать одноразово, не беспокоясь об установке или обновлении. Это потому, что вы можете просто создать экземпляр базы данных в контейнере на основе определенного образа докера. Нужно запустить базу данных определенной версии? Просто запустите образ докера в другом контейнере, который сопоставляется с другими портами.

Большинство программных компонентов доступны в виде образов докеров, включая RabbitMQ и MongoDB, в общедоступном репозитории образов докеров. Поэтому использование одноразовых образов докеров гораздо удобнее.

Что касается зависимости от внешней службы API, использование инструментов имитации API, таких как WireMock и Mock Server, позволяет проводить тестирование в отсутствие внешних служб API. На приведенной ниже диаграмме показана настройка локальной среды тестирования с помощью Docker и WireMock:

Запуск RabbitMQ и MongoDB с использованием контейнеров Docker

Docker позволяет нам определить программный стек в определении файла yaml, который называется docker compose. Определение docker compose (docker-compose.yml) ниже показывает программный стек RabbitMQ и MongoDB для службы обработки страховых требований.

В консоли терминала измените каталог на расположение docker-compose.yml, а затем выполните эту команду, чтобы открыть стек программного обеспечения.

docker compose up

Теперь вы сможете получить доступ к консоли администратора RabbitMQ http://localhost:15672 с учетными данными по умолчанию guest/guest.

Создание заглушек для API обслуживания клиентов с помощью WireMock

WireMock — прекрасный инструмент для тестирования без внешних API-сервисов. Он предоставляет гибкий способ создания макета API. Сценарий тестирования имитирует 3 записи клиентов с различными значениями атрибута риска ниже:

Эта команда запускает WireMock как автономный процесс и открывает порт 9999.

Java -jar wiremock.jar — port 9999

Посетите официальный веб-сайт WireMock, который предоставляет ссылку для загрузки jar-файла WireMock.

Мок-API — это просто сопоставление запроса с предопределенными данными ответа. В приведенном ниже примере файла JSON настраивается фиктивный ответ для трех разных записей о клиентах. Например, WireMock возвращает запись клиента с атрибутом высокого риска, когда получает запрос GET для URL.

GET /customers/C94C6168–6AED-46F9–9BA8-AA17793D41F9

Поместите JSON-файл клиента в папку mappings в текущем каталоге, где вы запускаете службу WireMock. Он автоматически создаст фиктивные ответы API на основе файлов JSON.

Конфигурация Spring Boot для локальной среды

Запустив контейнеры Docker и WireMock на локальном компьютере, подключите службу Spring Boot к компонентам с приведенной ниже конфигурацией. Вы можете видеть, что в конфигурации указан адрес службы клиентского API, Rabbitmq и MongoDB в качестве локального хоста.

Это новая конфигурация для профиля под названием «local-test», а файл конфигурации — application-local-test.yml, основанный на соглашении об именах файла конфигурации загрузки Spring — application-{имя профиля}.yml.

Настройка тестового примера

Теперь все готово. Настройка тестового примера довольно проста. Цель состоит в том, чтобы запустить приложение, которое подключается к Rabbitmq, MongoDB и имитации API обслуживания клиентов на вашем локальном компьютере. Использование аннотации @SpringBootTest и @ActiveProfiles для запуска тестовых случаев со всем контекстом приложения с указанным профилем «local-test»

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



Автоматизируйте создание контейнеров Docker и фиктивных API

До сих пор выполнение теста опиралось на ручную процедуру создания программного стека из Docker Compose и фиктивного сервера API. Это означает, что тесты не полностью автоматизированы, и поэтому тесты нельзя запускать в конвейере CI/CD, где выполнение процессов должно быть автоматизированным.

Чтобы автоматизировать процесс, программируемый интерфейс или командная строка должны быть доступны для программного кода для выполнения шагов. Не беспокойтесь, контейнеры Docker можно создавать с помощью библиотеки testcointainers, которая обеспечивает вызовы методов Java для операций с контейнерами, в то время как фиктивные API-интерфейсы могут создаваться динамически с помощью вызовов методов, предоставляемых WireMock. Вместе с настраиваемой логикой инициализации, поддерживаемой @SpringBootTest, диаграмма компонентов высокого уровня иллюстрирует процесс инициализации тестового примера.

Контейнеры Docker и WireMock API создаются и инициализируются на ранней стадии при запуске приложения Spring Boot. Контейнеры теперь являются одноразовыми ресурсами, которые создаются в начале и выбрасываются в конце выполнения теста.

@SpringBootTest создает весь контекст приложения, а затем запускает настраиваемый инициализатор, который создает контейнеры и сервер WireMock. Как только RabbitMQ, MongoDB и сервер WireMock будут запущены и запущены, имя хоста и порт службы будут внедрены в контекст приложения Spring Boot, чтобы приложение могло подключаться к компонентам. Поскольку контейнеры Docker и сервер WireMock можно запускать и привязывать к доступному порту, процесс инициализации полностью автоматизирован и не конфликтует с существующими службами на машине.

Зависимости Maven

Вам нужно будет добавить зависимость библиотеки тестовых контейнеров и wiremock в maven pom.xml.

<dependency>
  <groupId>org.testcontainers</groupId>
  <artifactId>junit-jupiter</artifactId>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.testcontainers</groupId
  <artifactId>mongodb</artifactId>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.testcontainers</groupId
  <artifactId>rabbitmq</artifactId>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>com.github.tomakehurst</groupId>
  <artifactId>wiremock-jre8</artifactId>
  <scope>test</scope>
</dependency>

Базовый класс тестирования компонентов

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

Инициализатор контекста тестирования компонента

Как вы можете видеть в @SpringBootTest выше, это относится к ComponentTestContextInitializer, который состоит из основного логического потока инициализации. Он делегирует задание TestContainerSetup и MockAPIServerSetup для инициализации контейнеров Docker и WireMock соответственно. После того, как компоненты среды готовы, этот инициализатор вводит конфигурацию подключения в свойства системы приложения, чтобы приложение могло подключаться к вновь созданным контейнерам Docker и фиктивному серверу API.

Автоматизация контейнеров Docker

Благодаря библиотеке testcontainers тестовый код может легко интегрироваться с контейнерами Docker. В приведенном ниже примере кода показано, как создать и запустить контейнер для MongoDB. Это просто и легко понять. Для доступа к контейнеру вызов getReplicaSetUrl() method возвращает URL-адрес с портом, который является доступным портом, сопоставленным с 27017.

MongoDBContainer mongoDBContainer = 
                    new MongoDBContainer("mongo")
                    .withExposedPorts(27017);
mongoDBContainer.start()
String mongoDBUrl = mongoDBContainer.getReplicaSetUrl();
// return mongoDBUrl: mongodb://localhost:55009/test

Чтобы лучше управлять инициализацией контейнеров, у нас есть служебный класс под названием TestContainersSetup, который отвечает за создание контейнеров. Затем инициализатор контекста приложения может вызвать свой метод initTestContainers() , чтобы запустить RabbitMQ и MongoDB и получить информацию о подключении.

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

Настройка фиктивного API-сервера

Точно так же у нас есть служебный класс для фиктивной конфигурации сервера API и настройки фиктивного ответа.

Пример тестового класса

Наконец, включите автоматизацию, обновив тестовый класс таким образом, чтобы он расширялся из базового класса.

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

mvn -Dtest=ClaimProcessingAutoEnvTest clean test

Последние мысли

Ожидается, что большая часть деятельности по тестированию будет автоматизирована в процессе разработки современного программного обеспечения. Не только выполнение тестовых случаев, но и настройка среды должны быть полностью автоматизированы, чтобы тесты могли выполняться в конвейере CI/CD. Внедрение автоматизации не является сложной задачей, работу можно выполнить с помощью контейнеров Docker, WireMock и JUnit. Ссылка на пример кода в репозитории GitHub дает вам вдохновение и ускоряет реализацию автоматизированного тестирования.

Основываясь на реализации автоматизированных тестов, добавление тестов с использованием файлов функций Cucumber значительно повышает удобочитаемость тестовых сценариев. Эта статья даст вам идеи с примерами кода, как создавать автоматические тесты с помощью Cucumber.