
Ich heiße Dmitrij, ich arbeite als Tester bei der Firma . Kürzlich habe ich mich mit einer relativ neuen Funktion von befasst — nämlich mit dem instrumentierten Testen von iOS-Anwendungen unter Verwendung des nativen Testframeworks XCUITest.
Zuvor hatte ich Firebase Test Lab für Android ausprobiert und war sehr zufrieden, also beschloss ich, die Testinfrastruktur des iOS-Projekts auf denselben Standard zu bringen. Ich musste viel googeln und nicht alles klappte beim ersten Versuch, weshalb ich beschloss, einen Tutorial-Artikel für diejenigen zu schreiben, die das gleiche vor sich haben.
Wenn Ihr also UI-Tests in Eurem iOS-Projekt habt, könnt Ihr sie schon heute auf echten Geräten ausprobieren, die freundlicherweise von der Wohltätigkeitsorganisation zur Verfügung gestellt werden. Interessierte sind herzlich eingeladen, weiterzulesen.
In der Darstellung habe ich mich auf einige Ausgangsdaten stützen wollen — ein privates Repository auf GitHub und das Build-System CircleCI. Der Name der Anwendung ist AmazingApp, bundleID ist com.company.amazingapp. Diese Daten beschreibe ich hier gleich, um spätere Verwirrungen zu vermeiden.
Falls Ihr bestimmte Lösungen in Eurem Projekt anders umgesetzt habt, teilt Eure Erfahrungen gerne in den Kommentaren.
1. Die Tests selbst
Wir erstellen einen neuen Branch für die UI-Tests:
$ git checkout develop
$ git pull
$ git checkout -b “feature/add-ui-tests”
Öffnen wir das Projekt in XCode und erstellen ein neues Ziel (Target) für die UI-Tests [XCode -> Datei -> Neu -> Ziel -> iOS Testing Bundle], und geben ihm einen aussagekräftigen Namen: AmazingAppUITests.

Gehen wir zum Abschnitt Build Phases des erstellten Targets und überprüfen, ob die Target Dependencies — AmazingApp, in Compile Sources — AmazingAppUITests.swift vorhanden sind.
Eine gute Praxis ist es, verschiedene Build-Varianten in separate Schemes zu gliedern. Wir erstellen ein Scheme für unsere UI-Tests [XCode -> Produkt -> Scheme -> Neues Scheme] und geben ihm denselben Namen: AmazingAppUITests.
Der Build des erstellten Schemas sollte das Target der Hauptanwendung — AmazingApp und das Target der UI-Tests — AmazingAppUITests enthalten — siehe Screenshot.

Erstellen wir als Nächstes eine neue Build-Konfiguration für die UI-Tests. In XCode klicken wir auf die Projektdatei, gehen in den Abschnitt Info. Klicken auf “+” und erstellen eine neue Konfiguration, beispielsweise XCtest. Dies wird später in einer möglichen Code-Signierung hilfreich sein.

In Eurem Projekt gibt es mindestens drei Targets: die Hauptanwendung, Unit-Tests (die gibt es, oder?) und das von uns erstellte Target für die UI-Tests.
Wir gehen in das Target AmazingApp, auf die Registerkarte Build Settings, Abschnitt Code Signing Identity. Für die XCtest-Konfiguration wählen wir iOS Developer. Im Abschnitt Code Signing Style wählen wir Manual. Das Provisioning-Profil haben wir noch nicht generiert, aber wir werden später darauf zurückkommen.
Für das Target AmazingAppUITests machen wir das Gleiche, aber in das Feld Product Bundle Identifier schreiben wir com.company.amazingappuitests.
2. Projekteinrichtung im Apple Developer Program
Wir gehen auf die Seite des Apple Developer Program, gehen zum Abschnitt Certificates, Identifiers & Profiles und dann in das Feld App IDs im Punkt Identifiers. Wir erstellen eine neue App ID mit dem Namen AmazingAppUITests und der Bundle ID com.company.amazingappuitests.

Jetzt haben wir die Möglichkeit, unsere Tests mit einem separaten Zertifikat zu signieren, aber… Der Build-Prozess für Tests umfasst den Build der App selbst und die Builds des Test-Runners. Entsprechend stehen wir vor dem Problem, zwei Bundle IDs mit einem Provisioning-Profil zu signieren. Glücklicherweise gibt es eine einfache und elegante Lösung — Wildcard App ID. Wir wiederholen den Prozess zur Erstellung einer neuen App ID, aber anstelle von Explicit App ID wählen wir Wildcard App ID wie auf dem Screenshot.

An diesem Punkt ist die Arbeit mit developer.apple.com beendet, aber wir werden das Browserfenster nicht schließen. Wir gehen zu und lesen von Anfang bis Ende über das Tool Match.
Ein aufmerksamer Leser hat bemerkt, dass wir für die Nutzung dieses Tools ein privates Repository und ein Konto benötigen, das sowohl Zugang zum Apple Developer Program als auch zu Github hat. Wir erstellen (falls noch nicht vorhanden) ein Konto wie InfrastructureAccount@your.company.domain, denken uns ein starkes Passwort aus, registrieren es bei developer.apple.com und machen es zum Administrator des Projekts. Danach geben wir dem Konto Zugang zum Github-Repository Ihres Unternehmens und erstellen ein neues privates Repository mit einem Namen wie AmazingAppMatch.
3. Einrichtung von Fastlane und dem Tool Match
Öffnen Sie das Terminal, gehen Sie in den Projektordner und initialisieren Sie Fastlane, wie in der angegeben. Nach Eingabe des Befehls
$ fastlane initwerden Sie aufgefordert, aus den verfügbaren Konfigurationen zu wählen. Wählen Sie den vierten Punkt — manuelle Projekteinstellung.

Im Projekt wurde ein neues Verzeichnis fastlane erstellt, in dem sich zwei Dateien befinden — Appfile und Fastfile. Kurz gesagt — im Appfile speichern wir die erforderlichen Daten, und im Fastfile definieren wir Jobs, die in der Terminologie von Fastlane als Lanes bezeichnet werden. Ich empfehle, die offizielle Dokumentation zu lesen: , .
Öffnen Sie das Appfile in Ihrem bevorzugten Texteditor und bringen Sie es wie folgt in Form:
app_identifier "com.company.amazingapp" # Bundle-ID
apple_dev_portal_id "infrastructureaccount@your.company.domain" # Erstellter Infrastruktur-Account, der das Bearbeiten des iOS-Projekts im Apple Developer Program ermöglicht.
team_id "LSDY3IFJAY9" # Ihre Developer Portal Team-ID
Wir kehren ins Terminal zurück und beginnen gemäß dem offiziellen Handbuch, match einzurichten.
$ fastlane match init
$ fastlane match development
Geben Sie nun die erforderlichen Daten ein – Repository, Konto, Passwort usw.
Wichtig: Bei der ersten Ausführung wird das Tool match nach dem Passwort zum Entschlüsseln des Repositories fragen. Es ist sehr wichtig, dieses Passwort zu speichern, da wir es später für die CI-Server-Konfiguration benötigen werden!
Im fastlane-Ordner wurde eine neue Datei namens Matchfile erstellt. Öffnen Sie sie in Ihrem bevorzugten Texteditor und passen Sie sie an:
git_url("https://github.com/YourCompany/AmazingAppMatch") #Erstelltes privates Repository zum Speichern von Zertifikaten und Profilen.
type("development") # Der Standardtyp kann sein: appstore, adhoc, enterprise oder development
app_identifier("com.company.amazingapp")
username("infrastructureaccount@your.company.domain") # Ihr Infrastructure-Account-Benutzername für das Apple Developer Portal
Füllen Sie es genau so aus, wenn Sie später match für das Signieren von Builds für die Veröffentlichung in Crashlytics und/oder im App Store verwenden möchten, d.h. für das Signieren der Bundle-ID Ihrer Anwendung.
Aber wie wir uns erinnern, haben wir eine spezielle Wildcard-ID für das Signieren des Test-Builds erstellt. Deshalb öffnen wir die Fastfile und fügen einen neuen Lane hinzu:
lane :testing_build_for_firebase do
match(
type: "development",
readonly: true,
app_identifier: "com.company.*",
git_branch: "uitests" # erstellen Sie einen eigenen Branch für das Entwicklungssignal für das Signieren des Test-Builds.
)
end
Speichern wir, und geben Sie im Terminal ein:
fastlane testing_build_for_firebaseund sehen, wie fastlane ein neues Zertifikat erstellt und es im Repository ablegt. Ausgezeichnet!
Öffnen Sie XCode. Jetzt haben wir das benötigte Provisioning-Profil in der Form Match Development com.company.*, das in dem Abschnitt Provisioning-Profil für die Ziele AmazingApp und AmazingAppUITests angegeben werden muss.

Es bleibt, den Lane für den Testbuild zu vervollständigen. Gehen Sie zu dem Plugin-Projekt für fastlane, das die Konfiguration des Exports in Firebase Test Lab erleichtert, und folgen Sie den Anweisungen.
Kopieren Sie aus dem ursprünglichen Beispiel, damit unser Lane testing_build_for_firebase am Ende so aussieht:
lane :testing_build_for_firebase do
match(
type: "development",
readonly: true,
app_identifier: "com.company.*",
git_branch: "uitests"
)
scan(
scheme: 'AmazingAppUITests', # UI Test-Schema
clean: true, # Empfohlen: Dies stellt sicher, dass der Build keine unnötigen Dateien enthält
skip_detect_devices: true, # Erforderlich
build_for_testing: true, # Erforderlich
sdk: 'iphoneos', # Erforderlich
should_zip_build_products: true, # Muss wahr sein, um das richtige Format für Firebase Test Lab zu setzen
)
firebase_test_lab_ios_xctest(
gcp_project: 'AmazingAppUITests', # Ihr Google Cloud-Projektname (zu dieser Zeile kommen wir später zurück)
devices: [ # Gerät(e), auf denen die Tests ausgeführt werden
{
ios_model_id: 'iphonex', # Geräte-Modell-ID, siehe gcloud-Befehl oben
ios_version_id: '12.0', # iOS-Version-ID, siehe gcloud-Befehl oben
locale: 'en_US', # Optional: Standard ist en_US, wenn nicht festgelegt
orientation: 'portrait' # Optional: Standard ist Hochformat, wenn nicht festgelegt
}
]
)
end
Für umfassende Informationen zur Konfiguration von fastlane in CircleCI empfehle ich, die offizielle Dokumentation zu lesen. .
Vergessen Sie nicht, unsere config.yml um eine neue Aufgabe zu ergänzen:
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 # Abhängigkeiten aktualisieren
- run:
name: gcloud-sdk installieren # Auf dem Mac muss gcloud installiert werden
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: App für Tests bauen
command: fastlane testing_build_for_firebase # Start des Build-Lanes und Übertragung zu Firebase
4. Und wie steht es um unsere Testumgebung? Lassen Sie uns Firebase einrichten.
Kommen wir nun zu dem, weshalb dieser Artikel geschrieben wurde.
Möglicherweise verwendet Ihre App Firebase im kostenlosen Tarif, vielleicht auch gar nicht. Es macht keinen wesentlichen Unterschied, denn für Testzwecke können wir ein separates Projekt mit einem Jahr kostenloser Nutzung erstellen (cool, oder?).
Loggen Sie sich in unser Infrastrukturkonto (oder ein beliebiges anderes, ist egal) ein und gehen Sie zu . Erstellen Sie ein neues Projekt mit dem Namen AmazingAppUITests.
Wichtig: Im vorherigen Schritt muss im Fastfile im Lane firebase_test_lab_ios_xctest der Parameter gcp_project mit dem Projektnamen übereinstimmen.

Die Standard Einstellungen sind für uns vollkommen in Ordnung.
Schließen Sie den Tab nicht, registrieren Sie sich mit demselben Konto bei – das ist eine notwendige Maßnahme, da die Kommunikation mit Firebase über die gcloud Console erfolgt.
Google schenkt 300 $ für ein Jahr, was im Kontext der Durchführung von automatisierten Tests einem Jahr kostenloser Nutzung des Dienstes entspricht. Wir geben die Zahlungsdaten ein, warten auf die Testabbuchung von 1 $ und erhalten 300 $ auf dem Konto. Nach einem Jahr wird das Projekt automatisch auf den kostenlosen Tarif umgestellt, sodass man sich keine Sorgen über einen möglichen Verlust von Geld machen muss.
Lassen Sie uns zum Tab mit dem Firebase-Projekt zurückkehren und es auf den Blaze-Tarif umstellen – jetzt haben wir etwas, mit dem wir die Überlimitkosten bezahlen können.
Im gcloud-Interface wählen wir unser Firebase-Projekt aus, wählen den Punkt im Hauptmenü „Katalog“ und fügen die Cloud Testing API und die Cloud Tools Result API hinzu.

Dann gehen wir zu dem Menüpunkt „IAM und Verwaltung“ -> Dienstkonten -> Dienstkonto erstellen. Wir gewähren Bearbeitungsrechte für das Projekt.

Wir erstellen einen API-Schlüssel im JSON-Format.

Das heruntergeladene JSON benötigen wir etwas später, während wir die Einrichtung des Testlabors als abgeschlossen betrachten.
5. Einrichtung von CircleCI
Eine berechtigte Frage drängt sich auf – was ist mit den Passwörtern? Um unsere Passwörter und andere sensible Daten sicher zu speichern, hilft uns der Mechanismus der Umgebungsvariablen unserer Build-Maschine. In den Projekteinstellungen von CircleCI wählen wir Umgebungsvariablen aus.

Und wir legen folgende Variablen an:
- key: GOOGLE_APPLICATION_CREDENTIALS
value: Inhalt der JSON-Datei des Dienstkonto-Schlüssels gcloud - key: MATCH_PASSWORD
value: Passwort zum Entschlüsseln des GitHub-Repositorys mit Zertifikaten - key: FASTLANE_PASSWORD
value: Passwort des Infrastrukturkontos im Apple Developer Portal
Wir speichern die Änderungen, erstellen einen PR und senden ihn zur Prüfung an unseren Teamleiter.
Ergebnisse
Infolgedessen haben wir durch diese einfachen Manipulationen eine gute, stabil arbeitende Umgebung mit der Möglichkeit erhalten, Videos vom Bildschirm des Geräts während der Durchführung der Tests aufzuzeichnen. In dem Testbeispiel habe ich das Modell des Geräts iPhone X angegeben, aber der Pool bietet eine reiche Auswahl an Kombinationen verschiedener Modelle und iOS-Versionen.
Der zweite Teil wird sich mit der schrittweisen Einrichtung des Firebase Test Lab für das Android-Projekt beschäftigen.
Quelle: habr.com
