[Из песочницы] Настраиваем автоматический запуск UI тестов Android приложения через TeamCity
Рано или поздно любой тестер, развивающий практики автотестирования, сталкивается с проблемой автономного выполнения своих тестов. Причем, если специалист опытный, то он старается столкнуться с этим как можно раньше. Так и я, после первого успешного прогона автотеста локально, решил сразу настроить запуск в TeamCity.
Отмечу, что у нас в компании экспертизы по удаленному запуску инструментальных тестов Android практически нет, поэтому приходилось усердно гуглить, но и там развернутых гайдов не нашел. Посему и решил запилить данную инструкцию.
На входе имеем:
- тест (-ы), успешно запускаемый локально
- работающий сервер TeamCity
- сервер на debian с KVM и иксами
Сразу дисклеймер по поводу сервера, где будет осуществляться запуск: настройка ОС, аппаратной виртуализации и графической оболочки не является предметом данной статьи и будет опущена.
Установка и настройка агента TeamCity
Начнем с Java. Тут главное правильно выбрать версию. У меня было 3 зависимости: сами тесты, android tools и агент teamcity. Остановился на версии 8, чтобы пользоваться одной JVM для всех. Если вам повезет меньше, и будут конфликты, то придется настраивать использование нескольких версий Java на одной машине. Еще заметка: если у вас debian, то сначала нужно добавить репозиорий webupd8team (гуглится очень быстро).
sudo apt-get install oracle-java8-installer
sudo apt-get install oracle-java8-set-default
Далее создаем пользователя, под которым будет запускаться агент и, соответственно, все остальное. Не забываем задать пароль.
sudo useradd -d /home/tc_agent -s /bin/bash -m tc_agent
sudo passwd tc_agent
Дистрибутив агента можно взять в веб интерфейсе вашего teamcity. Для этого перейдите в раздел Agents и справа вверху нажмите ссылку Install Build Agents. Скачайте и распакуйте в нужную папку на сервере (я рекомендую домашнюю папку нашего юзера — /home/tc_agent
). Далее добавьте права на запуск всем скриптам:
sudo chmod +x /home/tc_agent/BuildAgent/bin/*
Если ваша версия teamcity поддерживает Agent Push, то все еще проще. Просто откройте соответствующую вкладку в веб интерфейсе, нажмите кнопку Install Agent… и следуйте инструкциям.
Настраиваем конфиг. Если вы пользовались удаленной установкой, то он уже создан и в нем нужно только задать имя агента. Если нет, то создаем:
cd /home/tc_agent/BuildAgent/conf
cp buildAgent.dist.properties buildAgent.properties
nano buildAgent.properties
Заполняем serverUrl=
адресом веб интерфейса сервера, а name=
уникальным именем агента. Если у вас несколько агентов или дефолтный порт (9090) занят, то задайте свой с помощью параметра ownPort=
.
Запускаем командой /home/tc_agent/BuildAgent/bin/agent.sh start
. Если все настроено верно, то увидим наш агент на вкладке Unauthorized. Авторизовываем и можно пользоваться.
Для автоматического запуска агента создаем скрипт /etc/init.d/teamcity_agent
со следующим содержимым:
#!/bin/bash
BINARY="/home/tc_agent/BuildAgent/bin/agent.sh"
RUNAS="tc_agent"
LOGFILE="/home/tc_agent/BuildAgent/logs/start.log"
CMD="$BINARY $1 $2"
runuser - "$RUNAS" -c "$CMD > $LOGFILE"
cat $LOGFILE
Добавляем права на запуск sudo chmod +x /etc/init.d/teamcity_agent
и добавляем строку /etc/init.d/teamcity_agent start
в файл /etc/rc.local
.
Контрольная перезагрузка, агент поднялся, едем дальше.
Установка Android SDK и эмулятора
Скачиваем android sdk tools (Command line tools only) и распаковываем в нужную директорию. Создаем директорию для хранения будущих образов AVD (место должно быть достаточно). Для меня админы подключили основное хранилище в каталог /var,
туда и буду все складывать. Далее меняем владельца файлов на нашего пользователя и последующие действия лучше делать под ним.
sudo chown tc_agent -R /var/opt/android-sdk
sudo mkdir /var/opt/.android
sudo chown tc_agent /var/opt/.android
Добавляем переменные среды. Открываем на редактирование файл /home/tc_agent/.bash_profile
и прописываем:
export ANDROID_HOME=/var/opt/android-sdk
export ANDROID_AVD_HOME=/var/opt/.android/avd
export PATH=$ANDROID_HOME/platform-tools:$PATH
export PATH=$ANDROID_HOME/tools:$PATH
Перезагружаем и проверяем, что переменные корректно отображаются в веб интерфейсе teamcity на вкладке Agent Parameters.
Пробуем запустить sdkmanager: команда $ANDROID_HOME/tools/bin/sdkmanager --list
должна вывести список установленных и доступных пакетов. Если получили ошибку вида Exception in thread "main" java.lang.NoClassDefFoundError
, то попробуйте это решение.
Устанавливаем необходимые тулы и образ (-ы) виртуалок.
$ANDROID_HOME/tools/bin/sdkmanager emulator platform-tools tools
$ANDROID_HOME/tools/bin/sdkmanager 'system-images;android-25;google_apis;x86'
Создание и запуск AVD
Итак, скачали образ 'system-images;android-25;google_apis;x86'
(Android 7.1.1), создадим на его основе виртуальное устройство. Не буду вдаваться в подробности всех возможных параметров утилиты avdmanager, покажу на минимально возможном количестве:
$ANDROID_HOME/tools/bin/avdmanager create avd -n avd_name -k "system-images;android-25;google_apis;x86"
Передаем имя и исходный образ (должен быть скачен заранее через sdkmanager). Если вернулась ошибка, то добавьте флаг -v
, чтобы посмотреть текст.
Переходим к эмулятору. Для начала проверьте наличие папок emulator, platforms, platform-tools, system-images в директории SDK. platforms я создал руками, остальные создались при установке пакетов через sdkmanager. Далее проверим аппаратное ускорение. Должен быть такой ответ.
$ANDROID_HOME/emulator/emulator -accel-check
accel:
0
KVM (version 12) is installed and usable.
accel
Если будет ошибка доступа к /dev/kvm
, то добавляем права:
addgroup kvm
usermod -a -G kvm tc_agent
chown root:kvm /dev/kvm
Плюс мне еще потребовалось установить QEMU: sudo apt-get install qemu-kvm
Делаем релогон и проверяем эмулятор еще раз.
Если все ок, то пробуем запустить. Чтобы посмотреть глазами, подключимся к серверу по vnc. И запустим эмулятор:
$ANDROID_HOME/emulator/emulator @avd_name
Должно появиться такое окно:
Во время прогонов тестов будем запускать без графики, поэтому добавим параметр -no-window
.
Настраиваем build в TeamCity
Переходим к завершающему этапу — настройке автономного запуска наших тестов. У меня получился билд из 4 шагов.
1. Запуск эмулятора
nohup /var/opt/android-sdk/emulator/emulator @avd_name -no-snapshot-save -no-boot-anim -no-window -snapshot clean_snap_1 > start_emulator.log 2>&1&
Так как эмулятор «лочит» терминал, нужно отвязать процесс с помощью утилиты nohup (можно и по-другому — решать вам). На всякий случай сохраняем лог эмулятора в файл start_emulator.log
. Для запуска тестов я создал чистый снапшот (как это сделать читайте здесь) и добавил ключ -no-snapshot-save
, чтобы он не перезаписывался.
2. Ожидание загрузки устройства.
adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;'
Сначала ждем статус wait-for-device
, затем в цикле ждем когда переменная sys.boot_completed
вернет 1.
3. Запуск тестов. Здесь все индивидуально, вот мой пример:
./gradlew clean connectedAndroidTest
4. Закрываем эмулятор. Здесь пока сделал простое терминирование процесса.
kill -s 2 `pgrep qemu-system`
Но лучше, конечно, запоминать ID процесса при создании эмулятора. Это нужно будет когда начнем запускать тесты в несколько потоков, что случайно не «убить» не тот процесс.
На этом все, спасибо, что дочитали. Если будут замечания от более опытных коллег, то с удовольствием внесу правки в мануал.