Рано или поздно любой тестер, развивающий практики автотестирования, сталкивается с проблемой автономного выполнения своих тестов. Причем, если специалист опытный, то он старается столкнуться с этим как можно раньше. Так и я, после первого успешного прогона автотеста локально, решил сразу настроить запуск в 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 процесса при создании эмулятора. Это нужно будет когда начнем запускать тесты в несколько потоков, что случайно не «убить» не тот процесс.

На этом все, спасибо, что дочитали. Если будут замечания от более опытных коллег, то с удовольствием внесу правки в мануал.

Комментарии (0)