
Jmenuji se Dmitrij, pracuji jako tester v společnosti . Nedávno jsem se podíval na relativně novou funkci od — konkrétně na instrumentální testování iOS aplikací s využitím nativního testovacího frameworku XCUITest.
Dříve jsem si již vyzkoušel Firebase Test Lab pro Android a všechno se mi velmi líbilo, tak jsem se rozhodl zkusit nastavit testovací infrastrukturu pro iOS projekt na stejných kolejích. Musel jsem hodně googlit a ne všechno se podařilo na poprvé, takže jsem se rozhodl napsat článek-tutoriál pro ty, kteří si to ještě nevyzkoušeli.
Pokud máte UI testy na iOS projektu, můžete je již dnes zkusit spustit na skutečných zařízeních, laskavě poskytovaných Korporací Dobro. Zájemci — vítejte pod článkem.
V narativu jsem se rozhodl vycházet z některých výchozích dat — soukromý repozitář na GitHubu a systém sestavení CircleCI. Název aplikace — AmazingApp, bundleID — com.company.amazingapp. Tato data uvádím hned, aby se předešlo dalším zmatkům.
Pokud jste některá řešení ve svém projektu zrealizovali jinak — podělte se o zkušenosti v komentářích.
1. Samotné testy
Vytváříme novou větev projektu pro UI testy:
$ git checkout develop
$ git pull
$ git checkout -b "feature/add-ui-tests"
Otevřeme projekt v XCode a vytvoříme nový cíl (Target) s UI testy [XCode -> Soubor -> Nový -> Cíl -> iOS Testing Bundle], dáme mu výstižný název AmazingAppUITests.

Přejdeme do sekce Build Phases vytvořeného Targetu a zkontrolujeme přítomnost Target Dependencies — AmazingApp, v Compile Sources — AmazingAppUITests.swift.
Dobrou praxí je vyčlenění různých variant sestavení do samostatných Schémat (Schemes). Vytvoříme schéma pro naše UI testy [XCode -> Produkt -> Schéma -> Nové schéma] a dáme mu stejné jméno: AmazingAppUITests.
Sestavení vytvořeného schématu by mělo zahrnovat Target hlavní aplikace — AmazingApp a Target UI testů — AmazingAppUITests — viz screenshot.

Dále vytvoříme novou konfiguraci sestavení pro UI testy. V XCode klikneme na soubor projektu, přejdeme do sekce Info. Klikneme na „+“ a vytvoříme novou konfiguraci, například XCtest. To bude potřeba později, abychom se vyhnuli problémům, když dojde na podepisování kódu.

Ve vašem projektu existují minimálně tři Targety: hlavní aplikace, jednotkové testy (ty tam jsou, že ano?) a námi vytvořený Target UI testů.
Přejdeme do Targetu AmazingApp, na záložku Build Settings, část Code Signing Identity. Pro konfiguraci XCtest vybíráme iOS Developer. V části Code Signing Style vybíráme Manual. Provisioning profil jsme ještě nevytvořili, ale později se k němu určitě vrátíme.
Pro Target AmazingAppUITests uděláme to samé, ale do pole Product Bundle Identifier napíšeme com.company.amazingappuitests.
2. Nastavení projektu v Apple Developer Program
Přejdeme na stránku Apple Developer Program, v sekci Certificates, Identifiers & Profiles, pak do části App IDs v rámci Identifiers. Vytvoříme nový App ID s názvem AmazingAppUITests a bundleID com.company.amazingappuitests.

Nyní máme možnost podepisovat naše testy samostatným certifikátem, ale… Postup buildu pro testování zahrnuje sestavení samotné aplikace a sestavení test runneru. Tím se dostáváme k problému podepisování dvou bundle ID jedním provisioning profilem. Naštěstí existuje jednoduché a elegantní řešení — Wildcard App ID. Opakujeme postup vytvoření nového App ID, ale místo Explicit App ID vybíráme Wildcard App ID, jak je vidět na snímku.

V této fázi je práce s developer.apple.com u konce, ale zavírat okno prohlížeče nebudeme. Přejdeme na a přečteme si o nástroji Match od začátku do konce.
Pozorný čtenář si povšiml, že pro používání tohoto nástroje budeme potřebovat soukromý repozitář a účet, který má přístup jak k Apple Developer Program, tak k Githubu. Vytvoříme (pokud ho ještě nemáme) účet typu InfrastructureAccount@your.company.domain, vymyslíme silné heslo, zaregistrujeme ho v developer.apple.com a přidělíme mu roli administrátora projektu. Dále, dáme účtu přístup k github repozitáři vaší firmy a vytvoříme nový soukromý repozitář s názvem jako AmazingAppMatch.
3. Nastavení Fastlane a nástroje match
Otevřeme terminál, přejdeme do složky s projektem a inicializujeme fastlane, jak je uvedeno v . Po zadání příkazu
$ fastlane initbude nabídnuto vybrat dostupné konfigurace použití. Vybereme čtvrtou možnost – ruční nastavení projektu.

V projektu se objevila nová složka fastlane, ve které jsou dva soubory — Appfile a Fastfile. Stručně řečeno — v Appfile uchováváme informace a v Fastfile definujeme úkoly, v terminologii Fastlane nazývané lanes. Doporučuji přečíst oficiální dokumentaci: , .
Otevřeme Appfile ve svém oblíbeném textovém editoru a upravíme ho na následující podobu:
app_identifier "com.company.amazingapp" # Bundle ID
apple_dev_portal_id "infrastructureaccount@your.company.domain" # Vytvořený infrastrukturní účet, který má právo na úpravy iOS projektu v Apple Developer Program.
team_id "LSDY3IFJAY9" # ID vašeho vývojářského týmu na portálu
Vrátíme se do terminálu a podle oficiálního manuálu začneme nastavovat match.
$ fastlane match init
$ fastlane match development
Dále zadáme požadované údaje — repozitář, účet, heslo atd.
Důležité: při prvním spuštění nástroj match požádá o zadání hesla pro dešifrování repozitáře. Je velmi důležité si toto heslo uchovat, v průběhu nastavování CI serveru ho budeme potřebovat!
Ve složce fastlane se objevil nový soubor — Matchfile. Otevřeme ho v oblíbeném textovém editoru a přivedeme k této podobě:
git_url("https://github.com/YourCompany/AmazingAppMatch") #Vytvořený soukromý repozitář pro uchování certifikátů a profilů.
type("development") # Výchozí typ, může být: appstore, adhoc, enterprise nebo development
app_identifier("com.company.amazingapp")
username("infrastructureaccount@your.company.domain") # Uživatelské jméno vašeho infrastrukturního účtu na portálu Apple Developer
Vyplňujeme přesně tímto způsobem, pokud chceme v budoucnu používat match pro podepisování buildů pro nasazení do Crashlytics a/nebo AppStore, tzn. pro podepisování bundle ID vaší aplikace.
Ale, jak víme, pro podepsání testovacího buildu jsme vytvořili speciální Wildcard ID. Proto otevřeme Fastfile a zapíšeme nový lane:
lane :testing_build_for_firebase do
match(
type: "development",
readonly: true,
app_identifier: "com.company.*",
git_branch: "uitests" # vytváříme samostatnou větev pro certifikát vývoje pro podepisování testovacího buildu.
)
end
Uložíme, zadáme do terminálu
fastlane testing_build_for_firebasea vidíme, jak fastlane vytvořil nový certifikát a uložil ho do repozitáře. Skvělé!
Otevřeme XCode. Nyní máme potřebný provisioning profile typu Match Development com.company.*, který je třeba uvést v sekci Provisioning profile pro cíle AmazingApp a AmazingAppUITests.

Zbývá doplnit lane pro sestavení testů. Jdeme do projektu pluginu pro fastlane, který usnadňuje nastavení exportu do Firebase Test Lab a následujeme pokyny.
Kopírujeme z původního příkladu, aby náš lane testing_build_for_firebase nakonec vypadalo takto:
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 (ke této větě se vrátíme později)
devices: [ # Zařízení/í pro spuštění testů
{
ios_model_id: 'iphonex', # ID modelu zařízení, viz gcloud příkaz výše
ios_version_id: '12.0', # ID verze iOS, viz gcloud příkaz výše
locale: 'en_US', # Volitelné: výchozí nastavení na en_US, pokud není nastaveno
orientation: 'portrait' # Volitelné: výchozí nastavení na portrét, pokud není nastaveno
}
]
)
end
Pro získání podrobných informací o nastavení fastlane v CircleCI doporučuji přečíst oficiální dokumentaci .
Nezapomínáme doplnit náš config.yml novým úkolem:
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 # aktualizujeme závislosti
- run:
name: install gcloud-sdk # na mac stroj je třeba nainstalovat 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 # spouštíme lane sestavení a odesíláme do firebase
4. A co náš testovací server? Nastavujeme Firebase.
Pustíme se tedy do toho, kvůli čemu byl tento článek napsán.
Možná vaše aplikace používá Firebase na bezplatném tarifu, možná — vůbec. V podstatě není žádný rozdíl, protože pro potřeby testování můžeme vytvořit samostatný projekt s ročním bezplatným používáním (skvělé, že?)
Přihlásíme se do našeho infrastrukturního účtu (nebo jakéhokoli jiného, to je jedno) a jdeme na . Vytvoříme nový projekt s názvem AmazingAppUITests.
Důležité: V předchozím kroku v Fastfile v lane firebase_test_lab_ios_xctest by parametr gcp_project měl odpovídat názvu projektu.

Výchozí nastavení nám zcela vyhovují.
Záložku nezavíráme, pod stejným účtem se registrujeme v — to je nezbytný krok, protože komunikace s Firebase probíhá prostřednictvím rozhraní konzole gcloud.
Google dává 300 $ na rok, což v kontextu provádění automatizovaných testů odpovídá jednomu roku bezplatného používání služby. Zadejte platební údaje, počkejte na testovací stržení 1 $ a získejte 300 $ na účet. Po uplynutí roku bude projekt automaticky převeden na bezplatný tarif, takže se nemusíte obávat možné ztráty peněz.
Nyní se vraťme na kartu s projektem Firebase a převedeme ho na tarif Blaze — nyní máme co platit v případě překročení limitu.
V rozhraní gcloud vyberte náš projekt Firebase, z hlavního menu vyberte položku „Katalog“ a přidejte Cloud Testing API a Cloud Tools Result API.

Poté přejděte do nabídky „IAM a správa“ -> Služební účty -> Vytvořit služební účet. Udělte práva na úpravu projektu.

Vytvořte klíč API ve formátu JSON

Stáhnutý JSON nám bude potřebný později, zatím budeme považovat nastavení Test Lab za dokončené.
5. Nastavení CircleCI
Je na místě rozumná otázka — co dělat s hesly? Spolehlivě uložit naše hesla a další citlivé údaje nám pomůže mechanismus proměnných prostředí našeho buildovacího serveru. V nastavení projektu CircleCI vyberte proměnné prostředí.

A vytvořte následující proměnné:
- key: GOOGLE_APPLICATION_CREDENTIALS
value: obsah JSON souboru klíče služebního účtu gcloud - key: MATCH_PASSWORD
value: heslo pro dešifrování github repozitáře s certifikáty - key: FASTLANE_PASSWORD
value: heslo infrastrukturního účtu Apple Developer Portal
Uložte změny, vytvořte PR a zašlete ho na revizi svému vedoucímu týmu.
Závěry
Díky provedení těchto jednoduchých manipulací jsme získali dobré, stabilně fungující prostředí s možností nahrávat video ze obrazovky zařízení během provádění testování. V testovacím příkladu jsem uvedl model zařízení iPhone X, ale farmy nabízejí bohatý výběr kombinací různých modelů a verzí iOS.
Druhá část bude věnována krok za krokem nastavení Firebase Test Lab pro projekt Android.
Zdroj: habr.com
