Укрощение Docker Compose в тестировании
Docker Compose — это инструмент для управления одним или более контейнеров, каждый из которых представляет отдельный сервис и предназначен для разворачивания связанных сервисов. Данный инструмент входит в состав Docker.
Если в вашем проекте для работы приложения требуется поднимать несколько сервисов, этот инструмент вам подойдет.
В тестировании Docker Compose может применяться для запуска тестов в строго определенной и подготовленной среде, а также упростит запуск тестов и подготовку окружения.
Docker и Docker Compose — в чем разница?
Основное отличие Docker Compose от Docker состоит в том, что первый используется для управления несколькими контейнерами с сервисами, которые составляют приложение, а Docker выполняет управление лишь над отдельным сервис-контейнером. Например: DB + Frontend + Backend.
Основные команды docker-compose
- docker-compose build: сборка сервисов, описанных в конфигурационных файлах
- docker-compose up: запуск собранных сервисов из конфигурационного файла
- docker-compose up -d: запуск контейнеров на фоне с флагом -d
- docker-compose up --abort-on-container-exit: завершение работы всех сервисов в случае завершения одного из сервисов
- docker-compose run application make install: запуск сервисов application с выполнением внутри контейнера команды make install
- docker-compose down: остановка и удаление всех сервисов, которые были запущены с помощью up
- docker-compose stop: остановка всех сервисов, которые были запущены с помощью up (их можно будет перезапустить docker-compose start)
- docker-compose restart: перезапуск всех остановленных и запущенных сервисов
Практическая часть
Состоит из:
- сборки UI-тестов в Docker image,
- запуска Selenoid и Selenoid UI в Docker Compose,
- запуска тестов в контейнере.
В этой части покажем на примере тестирования интерфейса сайта testit.software, как запускать контейнеры Selenoid, Selenoid-UI и UI tests c помощью Docker Compose из терминала.
Приступим к выполнению:
1. Установите docker desktop
2. Создайте проект ‘ui-test’ с пакетным менеджером maven в intellij idea
3. Вставьте следующие зависимости в pom файл
xml: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 org.example ui-test jar 1.0-SNAPSHOT UTF-8 3.8.1 11 2.22.2 11 11 UTF-8 UTF-8 1.7.0 5.5.2 6.1.1 org.junit.jupiter junit-jupiter ${junit.jupiter.version} test com.codeborne selenide ${selenide.version} clean test org.apache.maven.plugins maven-compiler-plugin ${maven.compiler.plugin.version} UTF-8
4. Создайте следующую структуру папок и файлов
├───config(folder)
│ ├───browsers.json
├───src(folder)
│ └───test(folder)
│ ├───java(folder)
│ │ └───uiTest(folder)
│ │ ├───Locators(class)
│ │ ├───TestDocker(class)
│ └───resources(folder)
├───Dockerfile(file)
├───docker-compose.yml(file)
├───docker-compose-tests.yml(file)
5. Опишем локаторы для сайта https://temp.testit.software/ для выполнения следующих сценариев:
- Выполнить переход с главной страницы в раздел “О продукте” > ”Автоматизированное тестирование”;
- Выполнить переход с главной страницы в раздел “Версии” > ”Enterprise VS Cloud”;
- Выполнить переход с главной страницы в раздел “Цены” > “Enterprise”
Для этого опишем локаторы в классе Locators:
public class Locators { public void clickNavLink(String nameNavLink) { $x("//span[contains(normalize-space(.),'" + nameNavLink + "')]").click(); } public void clickSubNavLink(String nameSubNavLink) { $x("//a[contains(normalize-space(.),'" + nameSubNavLink + "')]").click(); } public void checkTextSubNavLink(String nameSubNavLink) { $x("//h1[@class='title intro__title']").shouldHave(Condition.ownText(nameSubNavLink)); } }
Далее напишем простые UI-автотесты для сайта https://temp.testit.software/ с переходом по разделам:
public class TestDocker { private Locators locators = new Locators(); private static void configurationRemote() { //Указание базовой url тестируемого сайта Configuration.baseUrl = "https://temp.testit.software/"; //Указание удаленной url для selenoid if(System.getenv("StartRemote").equals("yes")){ Configuration.remote = "http://kubernetes.docker.internal:4444/wd/hub"; } //Определение типа браузера = chrome Configuration.browser = "chrome"; //Отключение системы безопасности браузера System.setProperty("chromeoptions.args", "--no-sandbox"); //Параметры для игнорирования ошибок сертификта System.setProperty("chromeoptions.args", "--ignore-certificate-errors"); //Определение расширения браузера Configuration.browserSize = "1920x1080"; //Создаём объект класса DesiredCapabilities, используется как настройка вашей конфигурации с помощью пары ключ-значение DesiredCapabilities capabilities = new DesiredCapabilities(); //Включить поддержку отображения экрана браузера во время выполнения теста capabilities.setCapability("enableVNC",true); //Переопределяем Browser capabilities Configuration.browserCapabilities = capabilities; } @BeforeAll public static void setUp() { configurationRemote(); } @AfterAll public static void tearDown() { Selenide.closeWebDriver(); } @BeforeEach public void prepareForTest() { open("/"); } @Test @DisplayName("Переход в раздел 'О продукте' в подраздел 'Автоматизация тестирования'") public void aboutOfProductTest() { $("h1[class='title intro__title']").shouldHave(Condition.ownText("Единый интерфейс")); locators.clickNavLink("О продукте"); locators.clickSubNavLink("Автоматизация тестирования"); locators.checkTextSubNavLink("Автоматизация"); } @Test @DisplayName("Переход в раздел 'Версии' в подраздел 'Enterprise VS Cloud'") public void aboutOfVersionProductTest() { $("h1[class='title intro__title']").shouldHave(Condition.ownText("Единый интерфейс")); locators.clickNavLink("Версии"); locators.clickSubNavLink("Enterprise VS Cloud"); locators.checkTextSubNavLink("Cloud или Enterprise -- что выбрать?"); } @Test @DisplayName("Переход в раздел 'Цены' в подраздел 'Enterprise'") public void aboutOfPriceForProductTest() { $("h1[class='title intro__title']").shouldHave(Condition.ownText("Единый интерфейс")); locators.clickNavLink("Цена"); locators.clickSubNavLink("Enterprise"); $x("//h3[@class='form-calc__startup-title']").shouldHave(Condition.ownText("Скидка за кейс")); } }
6. Подготовим Dockerfile с UI-тестами:
FROM maven:3.6.3-jdk-11 WORKDIR /app COPY pom.xml . COPY src ./src
7. Подготовим docker-compose.yaml с запуском Selenoid и Selenoid-UI:
version: '3.5' networks: selenoid: services: selenoid: container_name: selenoid image: "aerokube/selenoid:latest-release" ports: - "4444:4444" volumes: - ./config/:/etc/selenoid/:ro - ./video:/opt/selenoid/video - ./logs:/opt/selenoid/logs - /var/run/docker.sock:/var/run/docker.sock command: ["-conf", "/etc/selenoid/browsers.json", "-container-network", "ui-test_selenoid", "-limit", "10", "-retry-count", "2"] networks: selenoid: selenoid-ui: container_name: selenoid-ui image: "aerokube/selenoid-ui:latest-release" links: - selenoid ports: - "8080:8080" command: ["--selenoid-uri", "http://selenoid:4444"] networks: selenoid:
Образ с тестами будет запускаться в отдельном контейнере от Selenoid т.к. Selenoid относится к серверной части, которую можно останавливать/запускать/оставить в запущенном состоянии, в зависимости от особенностей вашего проекта, а UI-тесты будут изменяться, поэтому их лучше запускать контейнере.
Подготовим docker-compose-tests.yml для запуска тестов:
version: '3.5' networks: selenoid: services: ui-tests: build: context: ./ dockerfile: ./Dockerfile environment: StartRemote: "yes" command: mvn clean test container_name: ui-tests ports: - 0.0.0.0:5555:5555
8. Подготовим конфигурацию для запуска браузера Chrome:
{ "chrome": { "default": "102", "versions": { "102.0_ru": { "port": "4444", "image": "selenoid/vnc:102.0", "env" : ["LANG=ru_RU.UTF-8", "LANGUAGE=ru_RU.UTF-8", "LC_ALL=ru_RU.UTF-8"], "additionalNetworks": ["ui-test_selenoid"] }, "102.0_en": { "port": "4444", "image": "selenoid/vnc:102.0", "env" : ["LANG=en_US.UTF-8", "LANGUAGE=en_US.UTF-8", "LC_ALL=en_US.UTF-8"], "additionalNetworks": ["ui-test_selenoid"] } } } }
9. Скачаем Image браузером Сhrome docker pull selenoid/vnc:102.0
10. Запустим Docker Compose с Selenoid+Selenoid-UI.
Для этого выполните команду из терминала из корня папки с проектом:
docker-compose -f docker-compose.yml up -d
При выполнении docker-compose будут скачаны образа в локальный(aerokube/selenoid:latest-release / aerokube/selenoid-ui:latest-release)/
Проверим результат запуска:
- Проверьте selenoid. Для этого перейдите по ссылке http://localhost:4444/status
Должно быть написано следующее:
{"total":10,"used":0,"queued":0,"pending":0,"browsers":{"chrome":{"102.0_en":{},"102.0_ru":{}}}}
- Проверьте selenoid-ui. Для этого перейдите по ссылке http://localhost:8080/
- Проверьте в правом верхнем углу статус CONNECTED для SSE и SELENOID
- Создайте тестовую сессию в браузере в вкладке CAPABALITIES
Примечание: в момент создания сессии и до ее остановки запускается docker контейнер selenoid/vnc:102.0. После удаления сессии-контейнер удаляется.
Если результат как на гифке выше — сессия создается, vnc доступ есть, ссылка testit.software — вы на верном пути!
11. Запустим Docker Compose с UI тестами.
Для этого выполните команду из терминала из корня папки с проектом:
docker-compose -f docker-compose-tests.yml up -d
При выполнении docker-compose для тестов сначала будет собран image с тестами, далее будут подгружены все нужные зависимости в докер контейнер, далее будет запущен контейнер с ui тестами.
Проверить работу можно в selenoid-ui по адресу http://localhost:8080/
Как можно улучшить запуск UI-тестов с Test IT?
-
Dockerfile добавить sh для запуска тестов;
-
Dockerfile добавить sh для проверки доступности selenoid с последующим запуском тестов;
-
Добавить запись видео с правилом записи всех или только fail тестов;
-
Связать автотесты c TMS системой Test IT. Инструмент позволяет экспортировать написанные автоматизированные тесты. Для этого потребуется адаптер(см. репик TestIT в github). Таким образом, вы заведете тест-кейсы в TMS систему;
-
Настроить WebHook для запуска автотестов из TMS Test IT. Это поможет запускать автотесты пользователю с достаточными правами прямо из TMS.
-
Автоматизировать процесс создания Тест-плана с наполнением его тестами (которые связаны с автотестами), публикацией результата выполнения автотестов c репортом. Таким образом на каждый прогон автотестов у вас будет создан отдельный тест-ран с репортом о прохождении. Для экспорта автотестов/создания тест-рана/наполнения его автотестами/публикацией результата выполнения вам поможет swagger документация от Test IT.