Новый релиз Test IT Enterprise ver. 4.6 Chamaeleon уже на сайте!

Как использовать Docker в тестировании

605

Тестировщики часто проводят тестирование в разных контурах различных версий приложений. Если вам нужно настроить окружение в контуре только по двум сервисам, то вопрос с docker не актуален. А если их 20? Появляется проблема с настройкой сред окружения. Тут приходит на помощь docker.

Что такое Docker

Docker — это ПО для автоматизации развертывания и управления приложениями в средах с поддержкой контейнеризации. Он помогает «упаковать» приложение со всем его окружением и зависимостями в образ, который достаточно просто разворачивается в контейнере в любой Linux системе.

Контейнер — это изолированный процесс, в который вы упаковываете свое приложение со всеми зависимостями.

Почему стоит использовать docker в тестах

  1. Проблема запуска тестов в команде без установки стека тестовых технологий (solenoid, браузеры и др.)

  2. Менее требовательный, чем виртуальная машина по ресурсам (масштабирование ограничивается только ресурсами памяти и процессора на узлах с docker)

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

  4. Использование TestContainers решает многие проблемы. Например, запуск kafka в docker для работы приложения или интеграционных сервисов.

Главными преимуществами докера является его простота и дружелюбность в поведении в инструментах автоматизации. Таким образом, с помощью docker вы всегда сможете подтянуть нужные вам образа с программным обеспечением из docker hub либо собрать образ самостоятельно (проблема с заявками по инсталляции доп. ПО на ваш сервер уходит в прошлое). Например, вы можете использовать готовые docker image: kafka, PostgreSQL, Selenoid и др. Также можно отметить, что запуск тестов можно выполнить с любого удобного вам сервера вместо агента. Данная технология кроссплатформенная, т.е. запускается в разных ОС.

К минусам можно отнести повышенной порог входа для работы, а также особенности масштабирования.

Сборка docker image, запуск docker контейнера, запуск тестов в контейнере

Практическая часть будет продемонстрирована на ОС Win.

Обратите внимание, что на Win и Mac используется не настоящий Docker, а виртуальные машины Linux, в которых работает Docker.

  1. Установите docker desktop

  2. Создайте проект с пакетным менеджером maven в intellij idea

  3. Вставьте следующие зависимости в pom файл

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.0.0
  com.testit.rest.assured
  rest-assured
  1.0-SNAPSHOT
  jar
  rest-assured-sample
  http://maven.apache.org
  
    UTF-8
    UTF-8
    1.7.0
    5.7.0
    4.2.0
    2.22.2
    3.8.1
  
  
    
      org.junit.platform
      junit-platform-launcher
      ${junit.platform.version}
    
    
      org.junit.jupiter
      junit-jupiter
      ${junit.jupiter.version}
    
    
      io.rest-assured
      rest-assured
      ${restAssured.version}
    
  
  
    install
    
      
        org.apache.maven.plugins
        maven-compiler-plugin
        ${maven-compiler-plugin.version}
        
          UTF-8
          1.8
          1.8
        
      
      
        maven-surefire-plugin
        
          true
        
        org.apache.maven.plugins
        ${maven-surefire-plugin.version}
      
    
  
 
  

          4. Создайте структуру папок

├───src

│   └───test

│       ├───java

│       │   └───com

│       │       ├───apiTests

│       │       ├───model

│       └───resources

         5. Создайте модели (DTO)

Создадим класс UserDTO с моделью для выполнения запросов GET, POST, PUT, DELETE в каталоге src/test/java/com/model:

public class UserDTO {
    public String name;
    public String job;
    public UserDTO(String name, String job) {
        this.name = name;
        this.job = job;
    }
}

         6. Напишем простой автотест для сайта https://reqres.in для запросов GET, POST, PUT, DELETE с разным способом валидации Response:

  • Тестирование запроса Get c проверкой status code = 200. Создайте класс GetRequestTest в каталоге src/test/java/com/apiTests с тестом getRequestCheckStatusCode:
public class GetRequestTest {
    @Test
    @DisplayName("Тестирование запроса Get c проверкой status code = 200")
    public void getRequestCheckStatusCode() {
        RestAssured.given()
                   .baseUri("https://reqres.in/")//---> Cтартовая URL
                        .relaxedHTTPSValidation()
                   .get("/api/users/2")//---> Endpoint для выполнения запроса GET
                   .then()
                   .statusCode(HttpStatus.SC_OK);//---> Проверка статус код
    }
}
  • Тестирование тестового запроса Put c обновлением данных Users по полю job. Создайте класс PostRequestTest в каталоге src/test/java/com/apiTests с тестом postRequestCheckStatusCode:
public class PostRequestTest {
    @Test
    @DisplayName("Тестирование тестового запроса Post с проверкой status code = 201")
    public void postRequestCheckStatusCode() {
        RestAssured.given()
                   .baseUri("https://reqres.in/")//---> Cтартовая URL
                        .relaxedHTTPSValidation()
                   .body(new UserDTO("morpheus", "leader"))//---> body для запроса с методом POST
                   .post("/api/users")//---> Endpoint для выполнения запроса GET
                   .then()
                   .statusCode(HttpStatus.SC_CREATED);//---> Проверка статус код
    }
}
  • Тестирование тестового запроса Put c обновлением данных Users по полю job. Создайте класс PutRequestTestкаталог src/test/java/com/apiTests с тестом putRequestCheckStatusCodeAndJsonBody:
public class PutRequestTest {
    @Test
    @DisplayName("Тестирование тестового запроса Put c обновлением данных Users по полю job")
    public void putRequestCheckStatusCodeAndJsonBody() {
        String id;
        id = RestAssured.given()
                   .baseUri("https://reqres.in/")//---> Cтартовая URL
        .relaxedHTTPSValidation()
        .body(new UserDTO("morpheus", "leader"))//---> body для запроса с методом POST
                        .post("/api/users")//---> Endpoint для выполнения запроса GET
                        .then()
                        .statusCode(HttpStatus.SC_CREATED)//---> Проверка статус код
                        .assertThat()
                        .body("name", Matchers.is("morpheus"))//---> Проверка Body по key и value в json
                        .body("job", Matchers.is("leader"))//---> Проверка Body по key и value в json
                        .extract()
                        .response()
                        .body()
                        .path("id");//---> указания поля из Response Json для извлечения данных
            RestAssured.given()
        .baseUri("https://reqres.in/")//---> Cтартовая URL
        .relaxedHTTPSValidation()                  .body(new UserDTO("morpheus", "test_it"))//---> body с обновленными данными для запроса с методом PUT
                   .post("/api/users" + id)//---> Endpoint для выполнения запроса GET
                   .then()
                   .statusCode(HttpStatus.SC_CREATED)//---> Проверка статус код
                   .assertThat()
                   .body("name", Matchers.is("morpheus"))//---> Проверка Body по key и value в json
                   .body("job", Matchers.is("test_it"));//---> Проверка Body по key и value в json
    }
}


  • Тестирование запроса Delete c удалением пользователя. Создайте класс DeleteRequestTest в каталоге src/test/java/com/apiTests с тестом deleteRequestCheckStatusCode:
public class DeleteRequestTest {
    @Test
    @DisplayName("Тестирование запроса Delete c удалением пользователя")
    public void deleteRequestCheckStatusCode() {
        int id;//---> Преобразование с int можно выполнять либо извлекать из Response значение id в виде строки
        id = Integer.parseInt(RestAssured.given()
                                         .baseUri("https://reqres.in/")//---> Cтартовая URL
                .relaxedHTTPSValidation()
                                         .body(new UserDTO("morpheus", "leader"))//---> body для запроса с методом POST
                                         .post("/api/users")//---> Endpoint для выполнения запроса GET
                                         .then()
                                         .statusCode(HttpStatus.SC_CREATED)//---> Проверка статус код
                                         .extract()
                                         .response()
                                         .body()
                                         .path("id"));//---> указания поля из Response Json для извлечения данных

        RestAssured.given()
                   .baseUri("https://reqres.in/")//---> Cтартовая URL
        .relaxedHTTPSValidation()
                   .delete("/api/users/" + id)//---> Endpoint для выполнения запроса GET
                   .then()
                   .statusCode(HttpStatus.SC_NO_CONTENT);//---> Проверка статус код
    }
}

             7. Создадим DockerFile

DockerFile — это инструкция по созданию образа. Создайте в корне проекта файл Dockerfile c содержимым:

#FROM maven:3.6.3-jdk-11 — базовый образ с предустановленным mvn 3.6.3 и jdk11
FROM maven:3.6.3-jdk-11
#RUN mkdir -p /usr/src/app — создание каталога /usr/src/app в контейнере
RUN mkdir -p /usr/src/app
#WORKDIR /usr/src/app — задаёт рабочую директорию для следующей инструкции.
WORKDIR /usr/src/app
#ADD . /usr/src/app — копирование файлов в директорию. см. ADD or COPY: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
ADD . /usr/src/app
# RUN mvn clean test — выполняет команду и создаёт слой образа. Используется для установки в контейнер пакетов. 
RUN or CMD: https://www.geeksforgeeks.org/difference-between-run-vs-cmd-vs-entrypoint-docker-commands/#:~:text=A%20CMD%20command%20is%20used,the%20last%20one%20gets%20executed. 
Можно указать .sh для построение сложной логики запуска тестов, например, проверка на доступность тестируемого приложения
RUN mvn clean test

              8. Выполним сборку docker image:

  • Откройте терминал intellij idea в корне проекта
  • Выполните команду: docker build -t test-docker:1.0 .

          docker — запуск команды Docker

          build — команда сборки образа Docker

          -t — присвоить образу tag с названием 1.0

          test-docker — имя образа

          . [точка] — указывает, что DockerFile находится в текущей папке

Результатом выполнения должно быть 

          [+] Building 40.6s (10/10) FINISHED

  • Проверьте Docker Desktop. В разделе images появился новый образ test-docker c tag 1.0 или введите в терминале команду: docker images

          docker — запуск команды Docker

          images — запуск команды вывода идентификаторов образов


        9. Выполните запуск тестов следующим образом:

  • docker run --name teststartdocker -p 4444:4444 test-docker:1.0

          docker — запуск команды Docker

          run — команда запуска образа Docker

          --name run-test-docker — присваивание имя контейнера

          -p 4444:4444 — порты на входе и выходе контейнера

          test-docker:1.0 — имя образа и версия(tag) для запуска контейнера

  • Результат выполнения:
    [INFO] Tests run: 7, Failures: 0, Errors: 0, Skipped: 0

           …

           [INFO] BUILD SUCCESS

  • Проверка запущенного контейнера docker ps -a

Примечание: можно использовать ключ -rm для удаление контейнера после его выполнения. Пример  docker run --rm --name teststartdocker -p 4444:4444 test-docker:1.0


10. Остановка docker контейнера выполняется следующим образом docker stop [NAME или IMAGE+TAG]

          Пример:

          docker stop  test-docker:1.0 

          docker stop  427835437fb9


11. Далее вы можете удалить контейнер или образ.

  • Удаление контейнера docker rm [NAME или IMAGE]

          Пример: docker rm 427835437fb9

       docker rm teststartdocker

  • Удаление образа docker rmi [REPOSITORY:TAG или IMAGE ID+TAG] (i от image) 

         Пример: docker rmi test-docker:1.0

   docker rmi 94847b9b00cd

Примечание: При изменении состава контейнера, вы не изменяете образ. 

Основные команды docker:

  1. docker ps — просмотр списка запущенных контейнеров

  2. docker pull — загрузка образа.

Как правило, образы создаются на основе базового — из Docker Hub, где есть множество уже готовых образов и которые ты можешь использовать, а не тратить время на создание собственного. Для загрузки образа используется команда docker pull.

  1. docker build — собирает образ.

Данная команда собирает образ Docker из файла докера (dockerfile) и контекста сборки. Контекст сборки — это набор файлов, расположенных по определенному пути.

  1. docker logs — смотрим логи

Позволяет просмотреть логи указанного контейнера. Можно использовать флаг -follow, чтобы следить за логами работающего контейнера, например, docker logs -follow my.

  1. docker run — запускаем контейнер на основе указанного образа.

  2. docker stop — останавливает контейнер.

Используется для «мягкой» остановки контейнера. Пример: docker stop  test-docker:1.0. Можно остановить не конкретный контейнер, а все запущенные — docker stop $(docker ps -a -q).

  1. docker kill — «убивает» контейнер.

Не пытается аккуратно завершить процесс, подобна системной команде kill. Как и в предыдущем случае, можно «убить» все контейнеры: docker kill $(ps -a -q).

  1. docker rm — удаляет контейнер.

  2. docker rmi — удаляет образ.

  3. docker volume ls — список томов. Данная команда показывает список томов, которые являются основным механизмом для хранения данных, генерируемых контейнерами Docker.


Причины и цели для использования docker в тестировании могут быть разными, но современные реалии развития этой технологии показывают, что контейнеризация будет развивается и поддерживаться, т.е. пройти мимо нее не получится. Запуск ваших тестов (модульных, интеграционных или E2E) в контейнерах облегчает поддержку громоздких тестовых сред и помогает оптимизировать конвейеры непрерывной интеграции. Контейнеризация тестов может сэкономить вашей организации время на отладку проблем, вызванных несоответствием версий программного обеспечения.  

В следующей статье познакомимся с Docker compose, создадим docker image с UI автотестами с запуском с помощью Maven.

Была ли статья полезной?