Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Мене звуть Дмитро, я працюю тестувальником у компанії MEL Наука. Зовсім недавно я перестав розбиратися з порівняно свіжою фічею від Firebase Test Lab — а саме, із інструментальним тестуванням iOS додатків із використанням нативного фреймворку тестування XCUITest.

До цього я вже спробував Firebase Test Lab для Android і мені все дуже сподобалося, тому я вирішив спробувати поставити тестову інфраструктуру iOS проекту на ті ж рейки. Доводилося дуже багато гуглити і не все виходило з першого разу, тому я вирішив написати статтю-туторіал для тих, кому це все ще належить.

Отже, якщо у вас є UI тести на iOS проекті, ви зможете вже сьогодні спробувати запустити їх на реальних девайсах люб'язно наданих Корпорацією Добра. Зацікавленим — ласкаво просимо під кат.

У розповіді я вирішив відштовхуватися від деяких вихідних даних - приватний репозиторій на GitHub та система складання CircleCI. Назва програми - AmazingApp, bundleID - com.company.amazingapp. Ці дані я наводжу відразу, зменшення наступної плутанини.

Якщо ті чи інші рішення у своєму проекті ви реалізували по-іншому — поділіться досвідом у коментарях.

1. Самі тести

Створюємо нову гілку проекту для UI тестів:

$ git checkout develop
$ git pull
$ git checkout -b “feature/add-ui-tests”

Відкриємо проект в XCode і створимо нову Мету (Target) з UI тестами [XCode -> File -> New -> Target -> iOS Testing Bundle], даємо їй назву AmazingAppUITests, що говорить.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Переходимо в секцію Build Phases створеного Target і перевіряємо наявність Target Dependencies - AmazingApp, Compile Sources - AmazingAppUITests.swift.

Хорошою практикою є виділення різних варіантів складання окремі Схеми (Schemes). Створюємо схему для наших UI тестів [XCode -> Product -> Scheme -> New Scheme] і даємо їй таку саму назву: AmazingAppUITests.

Build створеної схеми повинен включати в себе Target основної програми - AmazingApp і Target UI тестів - AmazingAppUITests - див.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Далі, створюємо нову конфігурацію збирання для UI тестів. У XCode клацаємо файл проекту, переходимо в секцію Info. Клацаємо на "+" і створюємо нову конфігурацію, наприклад XCtest. Це буде потрібно нам надалі, щоб уникнути танців з бубном коли справа дійде до code signing.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

У вашому проекті є принаймні три Target: основна програма, юніт тести (адже вони є, чи не так?) і створений нами Target UI тестів.

Заходимо до Target AmazingApp, вкладка Build Settings, розділ Code Signing Identity. Для конфігурації XCtest вибираємо iOS Developer. У розділі Code Signing Style вибираємо Manual. Provisioning profile ми ще не згенерували, але трохи згодом обов'язково до нього повернемося.

Для Target AmazingAppUITests робимо те саме, але в графу Product Bundle Identifier вписуємо com.company.amazingappuitests.

2. Налаштування проекту в Apple Developer Program

Заходимо на сторінку Apple Developer Program, переходимо до розділу Certificates, Identifiers & Profiles і потім у графу App IDs пункту Identifiers. Створюємо новий App ID з ім'ям AmazingAppUITests та bundleID com.company.amazingappuitests.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Тепер у нас є можливість підписувати наші тести окремим сертифікатом, але… Процедура складання білда для тестування передбачає складання самого додатка та складання раннера тестів. Відповідно, ми стикаємося з проблемою підпису двох bundle ID одним provisioning profile. Добре, існує просте та елегантне рішення – Wildcard App ID. Повторюємо процедуру створення нового App ID, але замість Explicit App ID вибираємо Wildcard App ID як на скріншоті.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

На цьому етапі роботу з developer.apple.com закінчено, але згортати вікно браузера ми не будемо. Ідемо на сайт з документацією щодо Fastlane і читаємо про утиліту Match від кірки до кірки.

Уважний читач зауважив, що для використання цієї утиліти нам знадобиться приватний репозиторій та обліковий запис, що має доступ як до Apple Developer Program, так і до Github. Створюємо (якщо раптом такого немає) акаунт виду [захищено електронною поштою], Вигадуємо потужний пароль, реєструємо його в developer.apple.com, призначаємо адміністратором проекту. Далі, даємо обліковий запис доступ до github репозиторію вашої компанії і створюємо новий приватний репозиторій з ім'ям на кшталт AmazingAppMatch.

3. Налаштування Fastlane та утиліти match

Відкриваємо термінал, переходимо в папку з проектом та ініціалізуємо fastlane як зазначено у офіційному мануалі. Після введення команди

$ fastlane init

буде запропоновано вибрати доступні конфігурації використання. Вибираємо четвертий пункт – ручне налаштування проекту.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

У проекті з'явилася нова директорія fastlane, в якій лежать два файли – Appfile та Fastfile. У двох словах - в Appfile ми зберігаємо службові дані, а в Fastfile прописуємо jobs, в термінології Fastlane звані lanes. Рекомендую до прочитання офіційну документацію: раз, два.

Відкриваємо Appfile у улюбленому текстовому редакторі та наводимо його до наступного вигляду:

app_identifier "com.company.amazingapp"       # Bundle ID
apple_dev_portal_id "[email protected]"  # Созданный инфраструктурный аккаунт, имеющий право на редактирование iOS проекта в Apple Developer Program.
team_id "LSDY3IFJAY9" # Your Developer Portal Team ID

Повертаємось у термінал і за офіційним мануалом починаємо налаштовувати match.

$ fastlane match init
$ fastlane match development

Далі вводимо дані, що запитуються - репозиторій, акаунт, пароль і т.д.

Важливо: при першому запуску утиліта match попросить ввести пароль для дешифрування репозиторію. Дуже важливо зберегти цей пароль, на етапі налаштування CI сервера він нам знадобиться!

У папці fastlane з'явився новий файл - Matchfile. Відкриваємо в улюбленому текстовому редакторі та наводимо до вигляду:

git_url("https://github.com/YourCompany/AmazingAppMatch") #Созданный приватный репозиторий для хранения сертификатов и профайлов.
type("development") # The default type, can be: appstore, adhoc, enterprise or development
app_identifier("com.company.amazingapp")
username("[email protected]") # Your Infrastructure account Apple Developer Portal username

Заповнюємо саме таким чином, якщо хочемо надалі використовувати match для підпису білдів для викладки в Crashlytics та/або AppStore, тобто для підпису bundle ID вашої програми.

Але, як пам'ятаємо, для підпису тестового білда ми створили спеціальний Wildcard ID. Тому відкриваємо Fastfile і вписуємо новий lane:

lane :testing_build_for_firebase do

    match(
      type: "development",
      readonly: true,
      app_identifier: "com.company.*",
      git_branch: "uitests"  # создаем отдельный бранч для development сертификата для подписи тестовой сборки.
    )

end

Зберігаємо, вводимо до терміналу

fastlane testing_build_for_firebase

і бачимо, як fastlane створив новий сертифікат і поклав його в репозиторій. Чудово!

Відкриваємо XCode. Тепер у нас є потрібний provisioning profile виду Match Development com.company.*, який потрібно вказати в секції Provisioning profile для таргетів AmazingApp та AmazingAppUITests.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Залишилося дописати lane для збирання тестів. Йдемо до репозиторій проекту плагіна для fastlane, що полегшує налаштування експорту в Firebase Test Lab і дотримуємося інструкцій.

Копіпастим з вихідного прикладу, щоб наш lane testing_build_for_firebase у результаті виглядав так:


 lane :testing_build_for_firebase do

    match(
      type: "development",
      readonly: true,
      app_identifier: "com.company.*",
      git_branch: "uitests"
    )

    scan(
      scheme: 'AmazingAppUITests',      # UI Test scheme
      clean: true,                        # Recommended: This would ensure the build would not include unnecessary files
      skip_detect_devices: true,          # Required
      build_for_testing: true,            # Required
      sdk: 'iphoneos',                    # Required
      should_zip_build_products: true,     # Must be true to set the correct format for Firebase Test Lab
    )

    firebase_test_lab_ios_xctest(
      gcp_project: 'AmazingAppUITests', # Your Google Cloud project name (к этой строчке вернемся позже)
      devices: [                          # Device(s) to run tests on
        {
          ios_model_id: 'iphonex',        # Device model ID, see gcloud command above
          ios_version_id: '12.0',         # iOS version ID, see gcloud command above
          locale: 'en_US',                # Optional: default to en_US if not set
          orientation: 'portrait'         # Optional: default to portrait if not set
        }
      ]
    )

  end

Для отримання повної інформації про налаштування fastlane у CircleCI рекомендую до читання офіційну документацію раз, два.

Не забуваймо доповнити наш config.yml новим завданням:

build-for-firebase-test-lab:
   macos:
     xcode: "10.1.0"   
   working_directory: ~/project
   shell: /bin/bash --login -o pipefail
   steps:
     - checkout
     - attach_workspace:
         at: ~/project
     - run: sudo bundle install     # обновляем зависимости
     - run:
         name: install gcloud-sdk   # на mac машину необходимо установить gcloud
         command: |
           ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null ; brew install caskroom/cask/brew-cask 2> /dev/null
           brew cask install google-cloud-sdk
     - run:
         name: build app for testing
         command: fastlane testing_build_for_firebase  # запускаем lane сборки и отправки в firebase

4. А як же тестовий стенд? Налаштовуємо Firebase.

Приступимо, власне, до того, навіщо стаття й писалася.

Можливо, ваш додаток використовує Firebase на безкоштовному тарифному плані, можливо, не використовує зовсім. Принципової різниці абсолютно немає, тому що для потреб тестування ми можемо створити окремий проект із роком безкоштовного використання (круто, так?)

Логін у наш інфраструктурний аккаунт (або будь-який інший, не має значення), і йдемо на сторінку консолі Firebase. Створюємо новий проект з ім'ям AmazingAppUITests.

Важливо: У попередньому кроці Fastfile в lane firebase_test_lab_ios_xctest параметр gcp_project повинен відповідати назві проекту.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Дефолтні налаштування нас цілком влаштовують.

Не закриваємо вкладку, під тим самим акаунтом реєструємось у Gcloud — це вимушений захід, оскільки спілкування з Firebase відбувається за допомогою інтерфейсу консолі gcloud.

Google дарує 300 $ на рік, що в контексті виконання автотестів еквівалентно року безкоштовного використання сервісу. Вводимо платіжні дані, чекаємо на тестове списання 1$ і отримуємо 300$ на рахунок. За рік проект буде автоматично переведений на безкоштовний тарифний план, так що хвилюватися про можливу втрату грошей не варто.

Повернімося на вкладку з проектом Firebase і переведемо його на тарифний план Blaze — тепер ми маємо чим платити у разі перевищення ліміту.

В інтерфейсі gcloud вибираємо наш Firebase проект, вибираємо пункт головного меню «Каталог» та додаємо Cloud Testing API та Cloud Tools Result API.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Потім переходимо до пункту меню «IAM та адміністрування» -> Сервісні облікові записи -> Створити сервісний обліковий запис. Видаємо права на редагування проекту.

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Створюємо API ключ у форматі JSON

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект

Завантажений JSON знадобиться нам трохи пізніше, а поки налаштування Test Lab вважатимемо закінченим.

5. Налаштування CircleCI

Назріває резонне питання – а що робити з паролями? Надійно зберегти наші паролі та інші чутливі дані нам допоможе механізм змінних оточення нашої білд-машини. У налаштуваннях проекту CircleCI вибираємо Environment Variables

Запускаємо інструментальні тести у Firebase Test Lab. Частина 1: iOS проект
І заводимо наступні змінні:

  • key: GOOGLE_APPLICATION_CREDENTIALS
    value: вміст json файлу ключа сервісного облікового запису gcloud
  • key: MATCH_PASSWORD
    value: пароль для дешифрування github репозиторія із сертифікатами
  • key: FASTLANE_PASSWORD
    value: пароль інфраструктурного облікового запису Apple Developer Portal

Зберігаємо зміни, створюємо PR та відправляємо на review своєму тимлід.

Підсумки

В результаті виконання цих нехитрих маніпуляцій ми отримали хороший, стабільно працюючий стенд з можливістю запису відео на екрані пристрою в момент тестування. У тестовому прикладі я вказав модель iPhone X, але ферма надає багатий вибір з комбінації різних моделей і версій iOS.

Друга частина буде присвячена покроковому настроюванню Firebase Test Lab для Android проекту.

Джерело: habr.com

Додати коментар або відгук