Все

Как поднять инфраструктуру для запуска автотестов Android в облаках

Статьи android
Привет! Меня зовут Денис Веренцов, я Android-инженер из команды Emcee. Это технопродукт Авито, универсальное решение для запуска iOS и Android-тестов, с его помощью можно быстрее выкатывать новые фичи пользователям и клиентам. В этой статье я расскажу, как можно развернуть облачную инфраструктуру для запуска нативных автотестов Android-приложений на основе разработанного нами решения.
Статья будет полезна тем, кто хочет организовать инфраструктуру для запуска тестов, но не обладает подходящим для этого «железом». Материал также будет интересен тем, у кого есть желание попробовать технологию Emcee в деле.

Emcee и его преимущества

Emcee — это инструмент для мобильных автотестов. С его помощью можно развернуть инфраструктуру для нативных автотестов Android/iOS и запускать тесты, эффективно утилизируя ресурсы и повышая time-to-market.
Основные преимущества Emcee:
  • эффективность: тесты запускаются сразу на всех доступных ресурсах, не нужно выделять отдельные пулы ресурсов под определенные запуски тестов;
  • автоматический менеджмент жизненного цикла эмуляторов;
  • гибкая конфигурация запуска тестов: разные стратегии деления тестов, повторы упавших тестов, настройка таймаутов и так далее.

Облачная инфраструктура

На мой взгляд, у облачной инфраструктуры есть свои плюсы и минусы.
Плюсы:
  • можно быстро получить «железо» в широком спектре конфигураций. Это бывает полезно при проведении быстрых экспериментов или тестировании новых технологий;
  • можно обратиться в техподдержку, если есть проблемы или вопросы;
  • некоторые провайдеры на первое время дают гранты или бонусные рубли — первые эксперименты можно проводить бесплатно.
Минусы:
  • пожалуй, самый главный минус — стоимость: аренда мощного сервера или виртуальной машины может быть очень дорогой. Это десятки или даже сотни тысяч рублей в месяц;
  • не у всех провайдеров есть возможность выделить машины с KVM. У каждого провайдера нужно уточнять этот момент через техподдержку или документацию, а также проверять доступность KVM вручную;
  • нужно отдельно решать вопросы безопасности, так как без дополнительной подготовки такая инфраструктура открыта для интернета;
  • если для тестов нужны дополнительные инструменты или данные из корпоративной сети, то нужно думать, как соединить облачную инфраструктуру и корпоративную сеть.
У Emcee есть ряд требований к железу, поэтому перед арендой облачных мощностей нужно убедиться, что железо соответствует требованиям.
Требования такие:
  • OS на базе Linux, Docker, KVM (Kernel-based Virtual Machine)*;
  • процессор с архитектурой x86-64;
  • достаточное количество ресурсов для запуска нескольких docker-контейнеров. Минимум 4 CPU и 8ГБ RAM.
*На данный момент наличие KVM является обязательным, так как эта технология позволяет значительно улучшить перформанс Android-эмулятора. Подробнее можно прочесть в официальной документации эмулятора.

Аренда облачных ресурсов

Для примера был выбран провайдер VK Cloud, на котором в качестве демонстрации я арендую подходящую виртуальную машину (далее ВМ).
Создадим новый инстанс ВМ. Я выбрал Ubuntu 22.04, 8 CPU и 16ГБ RAM, а также диск SSD на 100ГБ.
Обратите внимание, что изначально конфигурация NESTED-X-X не была доступна. Для её получения я написал в техподдержку и спросил, как можно получить работающий KVM или рабочую вложенную виртуализацию внутри моей ВМ.
Далее настраиваем сеть:
  1. Для доступа к ВМ я указал свой SSH-ключ. Ключ можно создать или указать свой в меню выбора ключа.
  2. Дополнительно я добавил настройку Firewall: добавил новую группу безопасности emcee, в которой указал, какой входящий трафик разрешен для моей ВM.
3.⠀В группе безопасности emcee я указал порты, необходимые для работы Emcee: 8081, 8082 и 41000.
Следующим шагом предлагается настроить резервное копирование. Я отключил эту опцию и далее выбрал «Создать инстанс».
Немного ждем, пока ВМ подготовится и запустится.
После этого можно подключаться к ВМ по SSH с помощью ключа, который мы указывали при создании ВМ. Дополнительно в общей информации о ВМ описан способ подключения.

Как подготовить инфраструктуру

Подключаемся к ВМ по SSH:
ssh -i vktest ubuntu@<VM ip address>
Проверяем доступность KVM
После успешного подключения нужно проверить, что KVM доступен на данной ВМ. Для этого нужно установить утилиты cpu-checker и libvirt-clients . Можно установить что-то одно, но для примера я установлю обе.
Устанавливаем cpu-checker:
sudo apt-get install cpu-checker
И после установки вызываем в консоли команду sudo kvm-ok, которая должна показать наличие или отсутствие KVM. Вывод команды, если KVM доступен:
INFO: /dev/kvm exists
KVM acceleration can be used
Если KVM недоступен, то вывод будет такой:
INFO: Your CPU does not support KVM extensions
KVM acceleration can NOT be used
Устанавливаем libvirt-clients:
sudo apt-get update && sudo apt-get install libvirt-daemon-system libvirt-clients
После установки вызываем в консоли команду virt-host-validate qemu. Вывод команды, если KVM доступен:
QEMU: Checking for hardware virtualization : PASS

QEMU: Checking if device /dev/kvm exists : PASS

QEMU: Checking if device /dev/kvm is accessible : FAIL (Check /dev/kvm is world writable or you are in a group that is allowed to access it)

QEMU: Checking if device /dev/vhost-net exists : PASS

QEMU: Checking if device /dev/net/tun exists : PASS

QEMU: Checking for cgroup 'cpu' controller support : PASS

QEMU: Checking for cgroup 'cpuacct' controller support : PASS

QEMU: Checking for cgroup 'cpuset' controller support : PASS

QEMU: Checking for cgroup 'memory' controller support : PASS

QEMU: Checking for cgroup 'devices' controller support : WARN (Enable 'devices' in kernel Kconfig file or mount/enable cgroup controller in your system)

QEMU: Checking for cgroup 'blkio' controller support : PASS

QEMU: Checking for device assignment IOMMU support : WARN (No ACPI DMAR table found, IOMMU either disabled in BIOS or not supported by this hardware platform)

QEMU: Checking for secure guest support : WARN (Unknown if this platform has Secure Guest support)
Если KVM недоступен, то вывод может быть примерно таким:
QEMU: Checking for hardware virtualization : FAIL (Host not compatible with KVM; HW virtualization CPU features not found. Only emulated CPUs are available; performance will be significantly limited)

QEMU: Checking if device /dev/vhost-net exists : PASS

QEMU: Checking if device /dev/net/tun exists : PASS

QEMU: Checking for cgroup 'cpu' controller support : PASS

QEMU: Checking for cgroup 'cpuacct' controller support : PASS

QEMU: Checking for cgroup 'cpuset' controller support : PASS

QEMU: Checking for cgroup 'memory' controller support : PASS

QEMU: Checking for cgroup 'devices' controller support : PASS

QEMU: Checking for cgroup 'blkio' controller support : PASS

QEMU: Checking for device assignment IOMMU support : WARN (Unknown if this platform has IOMMU support)

QEMU: Checking for secure guest support : WARN (Unknown if this platform has Secure Guest support)
В случае, если после проверок обнаружилось, что KVM недоступен, то нужно узнать у техподдержки, как его включить/получить. А если такой возможности нет, то следует сменить провайдера.

Запускаем инфраструктуру Emcee через Docker Compose

Система Emcee запускается на основе docker-контейнеров. Минимальный набор контейнеров включается в себя три контейнера с сущностями:
  1. очередь Emcee распределяет тесты по воркерам в завиcимости от стратегии распределения и повтора тестов;
  2. воркер Emcee запускает тесты и собирает их результаты, управляет жизненным циклом Android-эмуляторов, которые запускаются внутри контейнера;
  3. Artifactory — готовая система для менеджмента артефактов. Нужна для передачи файлов между воркерами и клиентами Emcee.
Так как используются docker-контейнеры, Emcee можно развернуть разными способами: через Docker или Docker Compose, а также через Kubernetes. Для простоты я выберу способ с Docker Compose, который можно установить по официальной документации.
Нам потребуется всего 2 файла, создадим docker-compose.yaml:
version: '3'

services:

emcee-queue-service:

image: avitotech/emcee-queue:21.5.0

container_name: emcee-queue-service

ports:

- 41000:41000

queue-worker:

image: avitotech/emcee-worker:21.5.0

env_file:

- emcee-worker.env

depends_on:

- emcee-queue-service

deploy:

replicas: 2

devices:

- "/dev/kvm:/dev/kvm"

emcee-artifactory:

image: docker.bintray.io/jfrog/artifactory-oss:7.63.11

container_name: emcee-artifactory

ports:

- 8081:8081

- 8082:8082

volumes:

- emcee_artifactory:/var/opt/jfrog/artifactory

volumes:

emcee_artifactory:
Создадим второй файл, где указываются переменные окружения для воркера emcee-worker.env:
EMCEE_WORKER_QUEUE_URL=http://emcee-queue-service:41000
EMCEE_WORKER_LOG_LEVEL=info
Имя хоста emcee-queue-service резолвится в локальный адрес контейнера с таким же именем.
Далее поднимаем контейнеры командой:
docker compose up -d
И проверяем, что поднятие прошло успешно:
> docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

b631f9f32fa2 avitotech/emcee-worker:21.1.0 "./entrypoint.sh" 45 seconds ago Up 45 seconds 41001/tcp ubuntu-queue-worker-2

600a8a769bff avitotech/emcee-worker:21.1.0 "./entrypoint.sh" 45 seconds ago Up 44 seconds 41001/tcp ubuntu-queue-worker-1

6f7f5aca1fc0 docker.bintray.io/jfrog/artifactory-oss:7.63.11 "/entrypoint-artifac…" 46 seconds ago Up 45 seconds 0.0.0.0:8081-8082->8081-8082/tcp, :::8081-8082->8081-8082/tcp emcee-artifactory

cd2c4c1cb7b3 avitotech/emcee-queue:21.1.0 "/usr/local/bin/entr…" 46 seconds ago Up 45 seconds 0.0.0.0:41000->41000/tcp, :::41000->41000/tcp emcee-queue-service
Дополнительно можно проверить логи контейнера с воркером и увидеть, что воркер готов к работе:
> docker logs --tail 2 b631f9f32fa2

[INFO] [HttpServer] 2024-08-23 08:00:33.610: REST server at 41001 port started

[INFO] [StartWorkerCommand] 2024-08-23 08:00:33.611: Worker is ready for work
Кроме запуска контейнеров нужно настроить Artifactory. Для этого нужно:
  1. зайти по адресу <ваш ip>:8082 и пройти первоначальную настройку. Для первого входа использовать первичные данные admin и password;
  2. создать новый репозиторий с типом Generic и именем на ваш выбор;
  3. создать нового юзера, данные которого будут использоваться в клиентах Emcee и в воркерах, либо включить анонимный доступ. Здесь важно выдать новому юзеру, в том числе анонимному, права на чтение/запись/удаление. Если создан новый юзер, то в конфигурации воркера нужно задать его username/password в файле конфигурации emcee-worker.env . Подробнее про конфигурацию воркера описано здесь.
Подробнее про настройку Artifactory можно прочесть в документации Emcee.
Отмечу, что если у вас уже есть готовый и настроенный Artifactory, то можно использовать его. Главное, чтобы Artifactory был доступен и для клиентов, и для воркеров Emcee.
На этом запуск и настройка Emcee завершены, наша система готова принимать тесты.

Запускаем тесты через Emcee

Для запуска тестов в Emcee нам нужен клиент Emcee, который можно скачать на странице с релизами.
Android-клиенты бывают двух видов:
  • cli-утилита;
  • Gradle plugin.
Я выберу cli-утилиту, которую можно установить разными способами.
Для запуска тестов нам потребуется файл с конфигурацией, например, config.yaml:
queue:

baseUrl: http://emcee-network-address:41000 # адрес очереди Emcee

tests:

configurations:

- platform: android

appApk: ./apks/regress-debug.apk

testApk: ./apks/regress-debug-androidTest.apk

testTimeout: 120

screenRecordConfiguration:

videoRecordStrategy: record_none

devices:

- sdkVersion: 31 # версия Android SDK, на которой будут запущены тесты на эмуляторе

deviceType: "default"

outputs:

- junit # включаю создание отчета JUnit

- allure # включаю загрузку файлов для Allure отчета

storage:

type: artifactory

baseUrl: http://emcee-network-address:8081/artifactory/ # адрес настроенной Artifactory

repository: emcee-transport

user: "emcee_user"

password: "emcee_password"
Здесь файлы apk с приложением и тестами я положил рядом с файлом конфига. Как показывает практика, разные команды по-разному создают apk в рамках своих конвейеров на CI. Поэтому можно указать свой путь до актуальных apk файлов.
Бинарный файл с cli-утилитой я скачал вручную и теперь мой запуск прогона тестов выглядит так:
./emcee run config.yaml --outdir=results
После прогона тестов я получаю финальный результат:
Emcee run finished.

Sent tests count: 12

Executed tests count: 12

Run status: Failed

Successful tests count: 10

Skipped tests count: 1

Skipped tests:

com.avito.emcee.regress.ExampleInstrumentedTest#assumptionFalse

Failed tests count: 1

Failed tests:

com.avito.emcee.regress.ExampleInstrumentedTest#failed

Tests results written to: /my/path/results/emcee_artifacts/c15f0e85-7f3a-4007-95cc-25101b3aa231

com.avito.emcee.client.internal.result.JobResultHasFailedTestsException: These tests have failed:

com.avito.emcee.regress.ExampleInstrumentedTest#failed
Таким образом, мы успешно запустили прогон тестов в Emcee.

Бонус: готовое облако

Для тех, кто не хочет заморачиваться с виртуальными машинами и провайдерами, можно попробовать сразу запустить тесты в нашем облаке Emcee Cloud. В Emcee Сloud не нужно платить за аренду мощностей, плата берется только за время выполнения тестов. А для всех новых клиентов мы даем бесплатную квоту в 300 минут на прогоны тестов.

Три главных факта про Emcee

В современном мире можно быстро арендовать мощности под любые задачи, в том числе под инфраструктуру для автотестов.
  • Инструмент Emcee позволяет быстро развернуть масштабируемую инфраструктуру для автотестов Android (как попробовать Emcee для iOS можно почитать здесь).
  • Для запуска Emcee нужен подходящий сервер с Docker Compose, на котором можно развернуть контейнеры с Emcee и Artifactory: Artifactory нужно настроить либо использовать готовый.
  • Для тех, у кого нет своего железа и кто не готов платить за его аренду, мы создали сервис Emcee Cloud, где можно запускать свои тесты в облаке.
Спасибо за уделенное время для статьи!