О чём эта статья?

Всем привет, меня зовут Кирилл и я Android-разработчик в Scanny. В прошлой статье, мы описали то, как будет выглядеть наш CI/CD, научились запускать статический анализатор кода, выполнять Unit-тестирование, собирать различные Build Flavors и отправлять их в нашу Telegram-группу.

В этой статье я покажу, как можно подключить и запустить Android-тесты в рамках CI/CD на примере Marathon Labs и Firebase Test Lab.

Цикл статей про CI/CD для Android состоит из:

  1. Настраиваем CI/CD Android-проекта, часть 1. Начало.

  2. Вы находитесь здесь.

  3. Настраиваем CI/CD Android-проекта, часть 3. Автоматизация публикации версий в Play Market.

Marathon Labs

Начнем наше Android-тестирование с Marathon Labs. Для начала регистрируемся на Marathon Labs Cloud и переходим в раздел с токенами.

После чего создаем новый токен доступа, он нам понадобится для того, чтобы связать наш CI/CD с Marathon Labs. Сам токен сохраняем в надежном месте.

Далее переходим в раздел с проектами и создаем новый проект, даем ему название и slug, он нам понадобится, чтобы потом привязать наши тесты к рабочему проекту. Этот этап опциональный, мы просто делаем это для удобства.

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

runAndroidTestsUsingMarathon:  
  stage: tests  
  script:  
  
    - ./gradlew app:assembleSomeBuildFlavorDebug  
    - ./gradlew app:assembleSomeBuildFlavorDebugAndroidTest  
  
    - VERSION="1.0.46"  
    - curl --location https://github.com/MarathonLabs/marathon-cloud-cli/releases/download/${VERSION}/marathon-cloud-v${VERSION}-{the archive we need} --output /tmp/marathon-cloud  
  
    - mkdir -p /marathon  
    - tar -xzf /tmp/marathon-cloud --directory /marathon  
    - mv /marathon/marathon-cloud-v${VERSION}-{the archive we need}/marathon-cloud /usr/local/bin/  
    - chmod +x /usr/local/bin/marathon-cloud  
  
    - marathon-cloud devices android  
    - marathon-cloud run android --application "app/build/outputs/apk/{build flavor name}/debug/{your apk's name}.apk" --test-application "app/build/outputs/apk/androidTest/{build flavor name}/debug/{your apk's name}-androidTest.apk" --name ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} --project ${MARATHON_CLOUD_PROJECT_ID}  
  rules:  
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'

Здесь мы собираем APK приложения, и тестовый APK.

 ./gradlew app:assembleSomeBuildFlavorDebug  
 ./gradlew app:assembleSomeBuildFlavorDebugAndroidTest  

Скачиваем Marathon Cloud CLI и сохраняем в указанную директорию.

- VERSION="1.0.46"  
- curl --location https://github.com/MarathonLabs/marathon-cloud-cli/releases/download/${VERSION}/marathon-cloud-v${VERSION}-{the archive we need} --output /tmp/marathon-cloud

Создаем новую директорию, куда будем распаковывать наш архив.

- mkdir -p /marathon  

И непосредственно распаковываем в эту директорию.

- tar -xzf /tmp/marathon-cloud --directory /marathon  

Перемещаем бинарный файл marathon-cloud в системную директорию /usr/local/bin/.

- mv /marathon/marathon-cloud-v${VERSION}-{the archive we need}/marathon-cloud /usr/local/bin/

Устанавливаем права на исполнение для marathon-cloud.

- chmod +x /usr/local/bin/marathon-cloud 

Печатаем в консоль список доступных устройств, на которых мы можем запускать наши тесты. Делать это не обязательно.

- marathon-cloud devices android

И наконец, запускаем наши тесты.

- marathon-cloud run android --application "app/build/outputs/apk/{build flavor name}/debug/{your apk's name}.apk" --test-application "app/build/outputs/apk/androidTest/{build flavor name}/debug/{your apk's name}-androidTest.apk" --name ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} --project ${MARATHON_CLOUD_PROJECT_ID}  

Где мы даем название для нашего теста, в данном случае имя ветки из нашего MR.

--name ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}

И указываем slug нашего проекта, чтобы привязать тесты к конкретному проекту.

--project ${MARATHON_CLOUD_PROJECT_ID}

ВАЖНО
Здесь, при работе с marathon-cloud мы не использовали команду --api-key, которая требует наш сгенерированный токен. Дело в том, что если мы определим переменную с названием MARATHON_CLOUD_API_KEY, то Marathon автоматически будет использовать ее, а значит нам не нужно каждый раз его указывать при работе с marathon-cloud.

Дополнительно напоминаю, что чувствительные секреты (токены, ключи и т.д.) лучше хранить за пределами Gitlab variables. Как пример, можно использовать Yandex Lockbox, Google Cloud Secret Manager или HashiCorp Vault.

Переменные окружения:

Название переменной

Описание

MARATHON_CLOUD_API_KEY

Наш токен, который мы сгенерировали ранее

MARATHON_CLOUD_PROJECT_ID

Slug проекта, который мы создавали ранее

CI_MERGE_REQUEST_SOURCE_BRANCH_NAME

Название ветки из нашего MR, подробнее тут

В целом на этом все, итогом имеем такую красоту.

Firebase Test Lab

Внимание, данные шаги описаны исходя из того, что Firebase уже подключен к проекту. С первоначальной настройкой Firebase будет немного посложнее, но делается это всего 1 раз.

В первую очередь в Google Cloud, необходимо подключить следующие 3 API в консоли разработчика:

  1. Cloud Functions API;

  2. Cloud Testing API;

  3. Cloud Tool Results API.

Для этого переходим в раздел APIs & Services, где в боковом меню ищем пункт Enabled APIs and Services и переходим туда.

Затем нажимаем на кнопку Enable APIs and Services и в поисковике вводим названия API, которые я указывал выше, подключаем их. Некоторые из них уже могут быть добавлены.

Далее необходимо создать сервисный аккаунт, который будет использоваться для тестирования. Для этого переходим в раздел IAM & Admin во вкладку Service Accounts и нажимаем на кнопку Create service acount.

В открывшемся окне заполняем название и описание. По поводу названия и описания - тут на ваш вкус и цвет. Далее, в разделе Grant this service account access to project задаем роль Editor. 3 шаг заполнять не обязательно.

Теперь необходимо создать JSON-ключ, чтобы связать Google Cloud с нашим CI/CD, для этого переходим в наш сервисный аккаунт.

Открываем вкладку Keys и нажимаем кнопку Add key.

Создаем новый ключ, выбираем формат ключа - JSON. После чего скачиваем ключ на наш ПК.

С настройкой все, определим наши переменные для дальнейшего использования.

Переменные окружения:

Название переменной

Описание

GOOGLE_CLOUD_PROJECT_ID

Id проекта в google cloud

SERVICE_ACCOUNT

JSON-ключ, который мы создали и скачали на предыдущем этапе, этот файл необходимо открыть и без изменений скопировать ключ сюда

Информацию по GOOGLE_CLOUD_PROJECT_ID, можно найти следующим образом:

Всё, теперь все подготовительные этапы пройдены и можно перейти к pipeline'ну.

runAndroidTestsUsingFirebase:  
  stage: tests  
  script:  
   
    - ./gradlew app:assembleSomeBuildFlavorDebug  
    - ./gradlew app:assembleSomeBuildFlavorDebugAndroidTest  
  
    - apt-get update  
    - apt install python3-pip --yes  
  
    - curl https://dl.google.com/dl/cloudsdk/channels/rapid/google-cloud-sdk.tar.gz --output /tmp/google-cloud-sdk.tar.gz  
    - mkdir -p /google  
    - tar zxf /tmp/google-cloud-sdk.tar.gz --directory /google  
    - /google/google-cloud-sdk/install.sh --quiet  
    - source /google/google-cloud-sdk/path.bash.inc  
  
    - gcloud components update  
    - gcloud config set project ${GOOGLE_CLOUD_PROJECT_ID}  
  
    - echo $SERVICE_ACCOUNT > /tmp/service-account.json  
    - gcloud auth activate-service-account --key-file /tmp/service-account.json  
  
    - gcloud firebase test android models list  
    - gcloud firebase test android versions list  
  
    - gcloud firebase test android run \
  --type instrumentation \
  --use-orchestrator \
  --app app/build/outputs/apk/{build flavor name}/debug/{your apk's name}.apk \
  --test app/build/outputs/apk/androidTest/{build flavor name}/debug/{your apk's name}-androidTest.apk \
  --device model=Pixel2,version=30,locale=ru,orientation=portrait 
  rules:  
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'

Здесь мы собираем APK приложения, и тестовый APK.

./gradlew app:assembleSomeBuildFlavorDebug  
./gradlew app:assembleSomeBuildFlavorDebugAndroidTest

Далее, обновляем списки пакетов, чтобы использовать актуальные версии.

- apt-get update  

Устанавливаем python и pip (система управления пакетами). --yes - чтобы не подтверждать установку вручную.

- apt install python3-pip --yes

Затем скачиваем Google Cloud SDK.

- curl https://dl.google.com/dl/cloudsdk/channels/rapid/google-cloud-sdk.tar.gz --output /tmp/google-cloud-sdk.tar.gz

Создаем новую директорию, куда будем распаковывать наш архив.

- mkdir -p /google  

Теперь необходимо распаковать скачанный архив в нашу директорию.

- tar zxf /tmp/google-cloud-sdk.tar.gz --directory /google

И установить данный SDK.

- /google/google-cloud-sdk/install.sh --quiet

Чтобы дальше работать с Google Cloud SDK из командной строки, загрузим все его переменные окружения и т.д. в наш PATH (В Linux, здесь система ищет исполняемые файлы, когда мы работаем с ними из командной строки).

- source /google/google-cloud-sdk/path.bash.inc

Теперь начинаем настраивать наш Google Cloud. Для этого обновим компоненты SDK.

- gcloud components update

Устанавливаем проект, с которым будем работать и который мы настроили до этого.

- gcloud config set project ${GOOGLE_CLOUD_PROJECT_ID}

Авторизуемся.

- echo $SERVICE_ACCOUNT > /tmp/service-account.json  
- gcloud auth activate-service-account --key-file /tmp/service-account.json

Опционально печатаем в консоль список доступных устройств, на которых мы можем запускать наши тесты, а так же версии ОС Android, доступные для тестирования.

- gcloud firebase test android models list  
- gcloud firebase test android versions list  

Заключительным этапом мы уже конфигурируем запуск наших Android-тестов в Firebase. Подробнее про то, как конфигурировать запуск можно прочитать в официальной документации.

- gcloud firebase test android run \
  --type instrumentation \
  --use-orchestrator \
  --app app/build/outputs/apk/{build flavor name}/debug/{your apk's name}.apk \
  --test app/build/outputs/apk/androidTest/{build flavor name}/debug/{your apk's name}-androidTest.apk \
  --device model=Pixel2.arm,version=30,locale=ru,orientation=portrait 

После тестирования будут сформированы отчеты, которые мы сможем просмотреть в консоли разработчика Firebase.

Заключение

Ну вот и все, мы рассмотрели варианты запуска наших Android-тестов с использованием 2-х сервисов: Marathon Labs и Firebase Test Lab. Надеюсь кому-нибудь эта статья поможет.

В следующей части я расскажу про загрузку release-сборок в Play Market, где мы подключим необходимые сервисы и настроим pipeline. Создание тэгов в Gitlab будет в этой же статье. организовывать работу будем на примере 2-х решений: Gradle Play Publisher и Fastlane.

Дополнительно мы соберем свой Docker Image со всем необходимым окружением, и далее будем использовать в нашем CI/CD. Благодаря этому нам не придется каждый раз устанавливать все инструменты (Python, awscli и другие.).

Еще увидимся!

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