Привет, я Денис Веренцов, Android-инженер из команды, которая разрабатывает Emcee — инструмент Авито для параллельного запуска мобильных автотестов.
В этой статье я расскажу, как работает Emcee: как его развернуть, и как он помогает запускать нативные автотесты для мобильных приложений на примере Android. А ещё бонусом покажу, как работает облачная версия Emcee, которая позволяет прогонять тесты прямо в браузере, без необходимости своей инфраструктуры.
Я уже рассказывал про Emcee в видео-формате — можно посмотреть на YouTube-канале AvitoTech. Здесь — текстовая версия.
Какие сложности могут возникать с автотестами
Прежде чем обсуждать Emcee, давайте поговорим о том, какие могут возникать проблемы с автотестами у инженеров.
Где запускать тесты. Когда тестов становится много, появляется такой вопрос.
Запускать тесты локально — долго. Например, у нас в Авито больше 4к автотестов на каждый пул-реквест. Прогон такого количества тестов на локальной машине займёт десятки часов.
Запускать тесты на удалённых машинах — много головной боли. Нужно думать, как организовать инфраструктуру, как управлять девайсами, будут ли это реальные девайсы или эмуляторы, как они будут подниматься и как останавливаться.
Как запускать тесты быстро, надёжно, и при этом эффективно использовать ресурсы. Например, если на каждый запуск тестов выделять фиксированный пул девайсов, то из-за неравномерного распределения тестов и времени их выполнения, часть девайсов будет простаивать до конца прогона.
Ещё примеры проблем:
Очереди при большом количестве пул-реквестов. Например, может возникнуть ситуация, когда для какого-то запуска тестов нужно уметь повышать приоритет, чтобы не ждать своей очереди.
Разные версии Android SDK. Например, нужно уметь между ними переключаться, когда тесты запускаются на разных версиях SDK.
Для решения этих сложностей мы и придумали Emcee.
Emcee — раннер для параллельного тестирования
Emcee — это раннер для параллельного запуска нативных автотестов для Android- и iOS-приложений. Он позволяет:
масштабировать количество тестов. Emcee сам распределяет тесты между машинами и предоставляет единый отчёт.
тестировать на своей инфраструктуре. Emcee можно самостоятельно развернуть на собственной инфраструктуре. Или вообще не тратить время на построение инфраструктуры, и тестировать в облаке (Emcee.cloud), но об этом чуть ниже.
автоматизировать процессы, чтобы быстрее узнавать об ошибках и посвящать больше времени разработке новой функциональности в продукте.
Первые 4 года мы использовали Emcee только для iOS, но теперь адаптировали систему и для запуска Android-тестов.
Как работает Emcee
Emcee состоит из трёх компонентов:
Очередь — распределяет тесты по воркерам и централизованно возвращает результат клиентам.
Воркеры — запускают тесты и эмуляторы, управляют ими и собирают результаты.
Клиенты — отправляют тесты в очередь и принимают результат от очереди. Клиенты бывают двух типов: gradle-плагин и консольная утилита. Они взаимозаменяемы и применяются в зависимости от того, что удобнее пользователю.
Допустим, у нас есть пул-реквест с тестами. Сделали видео о том, как в этом случае работает Emcee. Кратко:
Отправляем тесты через клиент в очередь → Очередь распределяет тесты по всем доступным на данный момент воркерам, либо ждёт, пока текущие воркеры освободятся → Воркеры начинают прогонять тесты и возвращают результаты в очередь → Освободившееся воркеры сразу получают новую порцию работы — это позволяет эффективнее утилизировать ресурсы.
После запуска всех тестов результаты, статус запуска и артефакты возвращаются обратно клиентам.
Как запускать тесты в Emcee
Для демонстрации работы Emcee я создал и настроил небольшой демо-проект для Android, который включает в себя 11 разных тестов. Также я добавил инструмент Allure, чтобы посмотреть отчёт по окончании прогона.
Вот как выглядит настройка gradle-плагина в корневом build.gradle.kts файле:
emcee {
// адрес очереди Emcee
queueBaseUrl.set("http://speed-mobile-releases:41000")
testTimeout.set(Duration.ofMinutes(1))
// настройки для Artifactory
artifactory {
user.set("")
password.set("")
baseUrl.set("http://speed-mobile-releases:8082/artifactory/")
repository.set("emcee-transport")
}
// другие параметры
job {
groupId.set("Emcee Android Demo")
groupPriority.set(1)
id.set("")
priority.set(1)
}
retries.set(1)
loggerConfiguration {
logLevel.set("debug")
printStackTrace.set(false)
}
devices {
addDevice(31, "default")
}
}
...
Подробнее про назначение параметров можно почитать в документации.
Найдём среди gradle-задач нужную и запустим прогон:
./gradlew emceeTestDefaultDebug
По окончании прогона видим в консоли, что не прошли 3 теста — так и задумано.
В новых версиях Emcee мы добавили улучшенный вывод результата, в котором отображается количество запущенных и выполненных тестов, и количество тестов с разными результатами прогона.
Давайте теперь заглянем в артефакты прогона. В Emcee они могут быть трёх видов: файлов для Allure-отчёта, логкатов по каждому тесту или видеозаписях экрана эмулятора.
Давайте посмотрим Allure-отчёт по тем файлам, которые скачал Emcee после прогона. В отчёте — подробная информация по всем тестам.
allure serve allure-results
Итак, мы успешно запустили тесты в Emcee на удалённой инфраструктуре и проверили, что тесты успешно запустились и по ним вернулись артефакты запуска.
Как развернуть Emcee на своей инфраструктуре
Для развёртывания Emcee на собственной инфраструктуре вам потребуются:
Linux-сервер;
KVM;
Docker,
Artifactory.
Artifactory нужен для передачи файлов внутри Emcee. Можно использовать либо уже существующую в вашей компании версию, либо развернуть open source версию рядом с Emcee.
Emcee можно запускать в Docker, а можно — использовать Docker Compose или Kubernetes. Если запускать через Kubernetes, получится более гибко настроить способ взаимодействия с воркерами на разных серверах, а также построить более масштабную систему с десятками и сотнями воркеров.
Настраиваем. Я покажу простой пример с Docker Compose, в котором мы запустим очередь и 10 воркеров.
Для этого понадобится файл docker-compose.yml, в котором будут указаны докер-образы Emcee и файл с переменными окружения для конфигурации воркера.
version: "3.9"
services:
emcee-queue-service:
image: avitotech/emcee-queue:20.0.0
container_name: emcee-queue-service
ports:
- 41000:41000
queue-worker:
image: avitotech/emcee-worker:20.0.0
env_file:
- emcee-worker.env
depends_on:
- emcee-queue-service
deploy:
replicas: 10
devices:
- "/dev/kvm:/dev/kvm"
emcee-artifactory:
image: docker.bintray.io/jfrog/artifactory-oss:latest
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
Подробнее о дополнительных переменных окружения для воркеров можно почитать в документации.
Также перед запуском тестов необходимо настроить Artifactory. О том, как это сделать, можно почитать в документации.
Разворачиваем систему командой docker compose up -d
Теперь проверим, что воркеры подключились к очереди. Это можно сделать с помощью специального скрипта — он прочитает последние строки со всех воркеров.
docker ps -aq -f name=queue-worker | xargs -I{} docker logs --tail=1 {}
Воркеры успешно подключились к очереди и подняли каждый свой сервер. Это значит, что всё прошло успешно. Воркеры Emcee готовы принимать тесты.
В новой версии Emcee мы улучшили процесс старта воркера. Теперь при старте и готовности воркера можно увидеть сообщение "Worker is ready for work".
Как использовать Emcee в облаке
Emcee можно не разворачивать на своей инфраструктуре, как мы делали выше, а запускать тесты с помощью графического интерфейса в облаке. Для этого у нас есть сервис Emcee Cloud, он позволяет прогонять тесты на Android и iOS в браузере.
1. Загружаем APK-файлы: тесты и само приложение. Можно также выбрать тип раннера — я указал AndroidJUnitRunner. В новой версии облака раннер ищется автоматически.
2. Выбираем тесты из APK-файла, которые нужно прогнать.
3. Выбираем нужную версию Android SDK — сейчас доступно 6 версий. Также на этом экране можно добавить переменные окружения для тестов.
Когда всё готово, можно запускать прогон тестов. В интерфейсе вы увидите, что тесты были распределены по воркерам и начали выполняться. По мере их выполнения они будут отображаться в UI.
По каждому тесту можно посмотреть статус и детали запуска: время выполнения, исключения.
Есть общий отчёт по прогону: сколько тестов прошло и сколько упало, как долго отрабатывали все тесты.
Из Emcee Cloud также можно выгрузить отчёт в формате Allure (если сам Allure есть в тестах) и Junit. А ещё можно запустить прогон на тех же файлах. Это может быть удобно, когда хочется запускать разные наборы тестов на одних и тех же файлах приложения.
Теперь вы знаете, какие проблемы можно решить с помощью Emcee и как быстро развернуть инфраструктуру для запуска автотестов.
Добавлю, что Emcee можно попробовать в разных вариациях уже сейчас:
on-premise,
cloud,
интеграция с Github Actions.
У нас в планах ещё много новых фичей и улучшений — следите за новостями в нашем TG-канале.
Полезные ссылки
Emcee
Автотесты в Авито
Доклад Алексея Шпирко — Автотесты в Авито. Зачем они, как помогают, сколько стоят.
Доклад Тимофея Солонина — Писать нативные автотесты для iOS сложно? Это пока вы их запускать не начнете!
Интервью с Русланом Мингалиевым — Как ускорить автотесты || AI технологии для написания тестов || Автотесты в @AvitoTech