
Казвам се Дмитрий, работя като тестер в компанията . Съвсем наскоро завърших с изучаването на сравнително новата функция от — именно, с инструменталното тестване на 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.

Преминаваме в секцията Build Phases на създадения Target и проверяваме за наличието на Target Dependencies — AmazingApp, в Compile Sources — AmazingAppUITests.swift.
Добра практика е различните варианти на сборките да се отделят в отделни Схеми (Schemes). Създаваме схема за нашите UI тестове [XCode -> Product -> Scheme -> New Scheme] и ѝ даваме същото име: AmazingAppUITests.
Сборката на създадената схема трябва да включва Target на основното приложение — AmazingApp и Target на UI тестовете — AmazingAppUITests — вижте скрийншота

След това, създаваме нова конфигурация на сборката за UI тестовете. В XCode кликваме върху файла на проекта, преминаваме в секцията Info. Кликваме на “+” и създаваме нова конфигурация, например XCtest. Това ще ни е нужно по-късно, за да избегнем сложности, когато дойде времето за кодово подписване.

В проекта ви има поне три обекти: основното приложение, модулните тестове (все пак са налични, нали?) и създадения от нас обект за UI тестове.
Влизаме в обекта AmazingApp, раздел Build Settings, част Code Signing Identity. За конфигурацията XCtest избираме iOS Developer. В секцията Code Signing Style избираме Manual. Provisioning profile все още не сме генерирали, но по-късно ще се върнем към него.
За обекта 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.

Сега имаме възможност да подписваме тестовете си с отделен сертификат, но… Процедурата за изграждане на билд за тестване предполага изграждане на самото приложение и изграждане на тестовия рънър. Съответно, срещаме се с проблема да подпишем два bundle ID с един provisioning profile. За щастие, съществува просто и елегантно решение — Wildcard App ID. Повтаряме процедурата за създаване на нов App ID, но вместо Explicit App ID избираме Wildcard App ID, както е на скрийншота.

На този етап работата с developer.apple.com е приключила, но няма да затваряме прозореца на браузъра. Отиваме на и четем за утилитата Match от корица до корица.
Внимателният читател е забелязал, че за използването на тази утилита ще ни е необходим приватен репозиторий и акаунт с достъп както до Apple Developer Program, така и до Github. Създаваме (ако такъв все още не съществува) акаунт от вида InfrastructureAccount@your.company.domain, измисляме силна парола, регистрираме го в developer.apple.com и назначаваме администратор на проекта. След това даваме на акаунта достъп до github репозитория на вашата компания и създаваме нов приватен репозиторий с име като AmazingAppMatch.
3. Настройка на Fastlane и утилитата match
Отваряме терминал, преминаваме в папката с проекта и инициализираме fastlane, както е посочено в . След въвеждане на командата
$ fastlane initще бъде предложено да изберем наличните конфигурации за използване. Избираме четвъртата точка — ръчна настройка на проекта.

В проекта се появи нова директория fastlane, в която има два файла — Appfile и Fastfile. С две думи — в Appfile съхраняваме служебни данни, а в Fastfile описваме jobs, наричани lanes в терминологията на Fastlane. Препоръчвам да се прочете официалната документация: , .
Отваряме Appfile в любимия си текстов редактор и го подготвяме в следния вид:
app_identifier "com.company.amazingapp" # Bundle ID
apple_dev_portal_id "infrastructureaccount@your.company.domain" # Създаденият инфраструктурен акаунт, който има право да редактира iOS проекта в Apple Developer Program.
team_id "LSDY3IFJAY9" # Вашият Team ID в Developer Portal
Връщаме се в терминала и по официалния наръчник започваме да конфигурираме match.
$ fastlane match init
$ fastlane match development
След това въвеждаме изискваните данни — репозитория, акаунт, парола и т.н.
Важно: при първото стартиране утилитата match ще поиска парола за декриптиране на репозитория. Много важно е да запомним тази парола, ще ни е нужна на етапа на настройката на CI сървъра!
В папката fastlane се появи нов файл — Matchfile. Отваряме в любимия си текстов редактор и го подготвяме в следния вид:
git_url("https://github.com/YourCompany/AmazingAppMatch") # Създаденият частен репозиторий за съхранение на сертификати и профили.
type("development") # Стандартният тип, може да бъде: appstore, adhoc, enterprise или development
app_identifier("com.company.amazingapp")
username("infrastructureaccount@your.company.domain") # Вашето потребителско име за инфраструктурен акаунт в Apple Developer Portal
Попълваме именно по този начин, ако искаме впоследствие да използваме 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.

Остава да допишем 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 ; 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 по безплатен тарифен план, а може и изобщо да не го използва. Няма съществена разлика, тъй като за тестови цели можем да създадем отделен проект с година безплатно ползване (готино, нали?)
Влизаме в нашия инфраструктурен акаунт (или всеки друг, без значение) и отиваме на . Създаваме нов проект с име AmazingAppUITests.
Важно: В предишната стъпка в Fastfile параметърът gcp_project в lane firebase_test_lab_ios_xctest трябва да отговаря на името на проекта.

Дефолтните настройки са напълно приемливи за нас.
Не затваряйте раздела, регистрираме се в Gcloud с същия акаунт. — това е задължителна мярка, тъй като комуникацията с Firebase се извършва чрез интерфейса на конзолата gcloud.
Google предлага 300 долара на година, което в контекста на изпълнението на автоматизирани тестове е еквивалентно на една година безплатно ползване на услугата. Въвеждаме платежните данни, изчакваме тестовото таксуване от 1 долар и получаваме 300 долара в сметката. След изтичането на годината проектът ще бъде автоматично преведен на безплатен план, така че не е нужно да се притеснявате за евентуални загуби.
Връщаме се на таба с проекта Firebase и го превеждаме на плана Blaze – сега имаме с какво да платим в случай на надвишаване на лимита.
В интерфейса на gcloud избираме нашия Firebase проект, избираме елемента от главното меню „Каталог“ и добавяме Cloud Testing API и Cloud Tools Result API.

След това преминаваме в менюто „IAM и администриране“ -> Служебни акаунти -> Създадете служебен акаунт. Даваме права за редактиране на проекта.

Създаваме API ключ в JSON формат.

Сваленият JSON ще ни е нужен малко по-късно, а засега настройката на Test Lab считаме за окончателна.
5. Настройка на CircleCI
Изниква разумен въпрос – какво да правим с паролите? За да запазим надеждно паролите и други чувствителни данни, механизмът на променливи среди на нашата билд машина ще ни помогне. В настройките на проекта CircleCI избираме Environment Variables.

И създаваме следните променливи:
- key: GOOGLE_APPLICATION_CREDENTIALS
value: съдържанието на json файла с ключа на служебния акаунт gcloud. - key: MATCH_PASSWORD
value: паролата за декодиране на GitHub репозитория с сертификатите. - key: FASTLANE_PASSWORD
value: паролата на инфраструктурния акаунт в Apple Developer Portal.
Запазваме промените, създаваме PR и го изпращаме на рецензия на нашия тимлидер.
Итог
В резултат на изпълнението на тези несложни манипулации получихме добър, стабилно работещ стенд с възможност за запис на видео от екрана на устройството по време на тестовете. В тестовия пример посочих модела на устройството iPhone X, но фермата предлага богат избор от комбинации на различни модели и версии на iOS.
Втората част ще бъде посветена на стъпка по стъпка настройка на Firebase Test Lab за Android проект.
Източник: habr.com
