
Mi chiamo Dmitriy, lavoro come tester in un'azienda . Recentemente ho iniziato a esplorare una nuova funzionalità di — in particolare, il testing strumentale delle applicazioni iOS utilizzando il framework di testing nativo XCUITest.
Prima di ciò, ho già provato Firebase Test Lab per Android e mi è piaciuto molto, quindi ho deciso di implementare l'infrastruttura di testing del progetto iOS sugli stessi binari. Ho dovuto cercare molte informazioni su Google e non tutto è riuscito al primo tentativo, quindi ho deciso di scrivere un articolo-tutorial per coloro che devono ancora affrontarlo.
Quindi, se avete dei test UI nel progetto iOS, oggi stesso potrete provarli su dispositivi reali gentilmente forniti dalla Corporazione del Bene. Chi è interessato è benvenuto qui sotto.
In questa narrazione, ho deciso di partire da alcuni dati di base — un repository privato su GitHub e il sistema di build CircleCI. Il nome dell'applicazione è AmazingApp, bundleID — com.company.amazingapp. Riporto questi dati subito, per ridurre la futura confusione.
Se hai implementato alcune soluzioni nel tuo progetto in modo diverso, condividi la tua esperienza nei commenti.
1. I test stessi
Creiamo un nuovo branch del progetto per i test UI:
$ git checkout develop
$ git pull
$ git checkout -b "feature/add-ui-tests"
Apriamo il progetto in XCode e creiamo un nuovo Target con i test UI [XCode -> File -> Nuovo -> Target -> iOS Testing Bundle], dandole un nome significante: AmazingAppUITests.

Passiamo alla sezione Build Phases del Target creato e controlliamo la presenza delle Target Dependencies — AmazingApp, e in Compile Sources — AmazingAppUITests.swift.
È buona prassi separare le diverse varianti di build in Schemi distinte. Creiamo uno schema per i nostri test UI [XCode -> Prodotto -> Schema -> Nuovo Schema] e diamo lo stesso nome: AmazingAppUITests.
La build dello schema creato deve includere il Target dell'app principale — AmazingApp e il Target dei test UI — AmazingAppUITests — vedi screenshot.

Successivamente, creiamo una nuova configurazione di build per i test UI. In XCode clicchiamo sul file di progetto, passiamo alla sezione Info. Clicchiamo su “+” e creiamo una nuova configurazione, ad esempio XCtest. Questo ci sarà utile in seguito, per evitare complicazioni quando arriveremo alla firma del codice.

Nel tuo progetto ci sono almeno tre Target: l'app principale, i test unitari (dovrebbero esserci, giusto?) e il Target UI dei test che abbiamo creato.
Accediamo al Target AmazingApp, alla scheda Build Settings, sezione Code Signing Identity. Per la configurazione XCtest selezioniamo iOS Developer. Nella sezione Code Signing Style scegliamo Manual. Il profilo di provisioning non è stato ancora generato, ma ci torneremo più tardi.
Per il Target AmazingAppUITests facciamo la stessa cosa, ma nel campo Product Bundle Identifier inseriamo com.company.amazingappuitests.
2. Configurazione del progetto nell'Apple Developer Program
Accediamo alla pagina dell'Apple Developer Program, andiamo nella sezione Certificates, Identifiers & Profiles e poi nel campo App IDs della voce Identifiers. Creiamo un nuovo App ID con il nome AmazingAppUITests e bundleID com.company.amazingappuitests.

Ora abbiamo la possibilità di firmare i nostri test con un certificato separato, ma... La procedura di build per il test implica la build dell'app stessa e della build del runner dei test. Di conseguenza, ci troviamo di fronte al problema di firmare due bundle ID con un solo provisioning profile. Fortunatamente, esiste una soluzione semplice ed elegante: il Wildcard App ID. Ripetiamo la procedura di creazione di un nuovo App ID, ma invece di Explicit App ID scegliamo Wildcard App ID come mostrato nello screenshot.

A questo punto il lavoro su developer.apple.com è finito, ma non chiudiamo la finestra del browser. Andiamo su e leggiamo tutto sulla utility Match.
Il lettore attento avrà notato che per utilizzare questa utility abbiamo bisogno di un repository privato e di un account che abbia accesso sia al programma Apple Developer che a Github. Creiamo (se non esiste già) un account del tipo InfrastructureAccount@your.company.domain, scegliamo una password robusta, registriamolo su developer.apple.com e nominiamo amministratore del progetto. Poi, diamo all'account accesso al repository GitHub della vostra azienda e creiamo un nuovo repository privato con un nome tipo AmazingAppMatch.
3. Configurazione di Fastlane e della utility match
Apriamo il terminale, andiamo nella cartella del progetto e inizializziamo fastlane come indicato nel . Dopo aver inserito il comando
$ fastlane initverrà chiesto di scegliere le configurazioni di utilizzo disponibili. Selezioniamo il quarto punto — configurazione manuale del progetto.

Nel progetto è apparsa una nuova directory fastlane, contenente due file — Appfile e Fastfile. In breve: nell'Appfile conserviamo i dati di servizio, mentre nel Fastfile definiamo i lavori, denominati lanes nel gergo di Fastlane. Consiglio di leggere la documentazione ufficiale: , .
Apriamo l'Appfile con il nostro editor di testo preferito e portiamolo alla seguente configurazione:
app_identifier "com.company.amazingapp" # ID Bundle
apple_dev_portal_id "infrastructureaccount@your.company.domain" # Account infrastrutturale creato, autorizzato a modificare il progetto iOS nel Apple Developer Program.
team_id "LSDY3IFJAY9" # Il tuo Team ID del Portale Sviluppatore
Torniamo nel terminale e seguendo il manuale ufficiale cominciamo a impostare match.
$ fastlane match init
$ fastlane match development
Successivamente, inseriamo i dati richiesti — repository, account, password, ecc.
Importante: alla prima esecuzione, l'utility match chiederà di inserire la password per decriptare il repository. È molto importante conservare questa password, sarà utile durante la configurazione del server CI!
Nella cartella fastlane è comparso un nuovo file — Matchfile. Apriamolo con il nostro editor di testo preferito e modifichiamolo nel seguente modo:
git_url("https://github.com/YourCompany/AmazingAppMatch") # Repository privato creato per memorizzare certificati e profili.
type("development") # Il tipo predefinito può essere: appstore, adhoc, enterprise o development
app_identifier("com.company.amazingapp")
username("infrastructureaccount@your.company.domain") # Il tuo username dell'Apple Developer Portal per l'account infrastructure
Compiliamo esattamente in questo modo, se vogliamo usare in seguito match per firmare le build da pubblicare su Crashlytics e/o AppStore, cioè per firmare il bundle ID della tua applicazione.
Ma, come ricordiamo, per firmare la build di test abbiamo creato un Wildcard ID speciale. Pertanto, apriamo il Fastfile e inseriamo un nuovo lane:
lane :testing_build_for_firebase do
match(
type: "development",
readonly: true,
app_identifier: "com.company.*",
git_branch: "uitests" # Creiamo un branch separato per il certificato di sviluppo per firmare la build di test.
)
end
Salviamo, digitiamo nel terminale
fastlane testing_build_for_firebasee vediamo come fastlane ha creato un nuovo certificato e lo ha posizionato nel repository. Ottimo!
Apriamo XCode. Ora abbiamo il provisioning profile necessario del tipo Match Development com.company.*, da specificare nella sezione Provisioning profile per i target AmazingApp e AmazingAppUITests.

Rimane da scrivere un lane per compilare i test. Andiamo a progetto del plugin per fastlane che semplifica la configurazione dell'esportazione in Firebase Test Lab e seguiamo le istruzioni.
Copia e incolla dall'esempio sorgente affinché il nostro lane testing_build_for_firebase alla fine appaia così:
lane :testing_build_for_firebase do
match(
type: "development",
readonly: true,
app_identifier: "com.company.*",
git_branch: "uitests"
)
scan(
scheme: 'AmazingAppUITests', # Schema test UI
clean: true, # Raccomandato: questo garantirà che la build non includa file non necessari
skip_detect_devices: true, # Richiesto
build_for_testing: true, # Richiesto
sdk: 'iphoneos', # Richiesto
should_zip_build_products: true, # Deve essere vero per impostare il formato corretto per Firebase Test Lab
)
firebase_test_lab_ios_xctest(
gcp_project: 'AmazingAppUITests', # Il nome del tuo progetto Google Cloud (torneremo su questa riga più tardi)
devices: [ # Dispositivo(i) su cui eseguire i test
{
ios_model_id: 'iphonex', # ID modello dispositivo, vedi comando gcloud sopra
ios_version_id: '12.0', # ID versione iOS, vedi comando gcloud sopra
locale: 'en_US', # Facoltativo: predefinito a en_US se non impostato
orientation: 'portrait' # Facoltativo: predefinito a portrait se non impostato
}
]
)
end
Per informazioni complete sulla configurazione di fastlane in CircleCI, consiglio di leggere la documentazione ufficiale. .
Non dimentichiamo di aggiungere al nostro config.yml un nuovo task:
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 # aggiorniamo le dipendenze
- run:
name: install gcloud-sdk # sulla macchina mac è necessario installare 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 # avviamo la lane di costruzione e invio a firebase
4. E il nostro ambiente di test? Configuriamo Firebase.
Cominciamo, dunque, con l'obiettivo per cui è stato scritto l'articolo.
Forse la tua applicazione utilizza Firebase con un piano gratuito, o forse non lo utilizza affatto. Non c'è alcuna differenza fondamentale, perché per scopi di test possiamo creare un progetto separato con un anno di utilizzo gratuito (fantastico, vero?).
Accediamo al nostro account infrastrutturale (o a qualsiasi altro, non fa differenza) e andiamo alla . Creiamo un nuovo progetto con il nome AmazingAppUITests.
Importante: Nella fase precedente, nel Fastfile, nel lane firebase_test_lab_ios_xctest, il parametro gcp_project deve corrispondere al nome del progetto.

Le impostazioni predefinite ci soddisfano pienamente.
Non chiudiamo la scheda, ci registriamo con il stesso account su — è una misura obbligata, poiché la comunicazione con Firebase avviene tramite l'interfaccia della console gcloud.
Google offre 300$ per un anno, che nel contesto dell'esecuzione di test automatici equivale a un anno di utilizzo gratuito del servizio. Inseriamo i dati di pagamento, attendiamo l'addebito di prova di 1$ e otteniamo 300$ sul conto. Trascorso un anno, il progetto verrà automaticamente trasferito al piano gratuito, quindi non c'è motivo di preoccuparsi di una possibile perdita di denaro.
Torniamo alla scheda con il progetto Firebase e lo trasferiamo al piano Blaze — ora abbiamo i mezzi per pagare nel caso si superi il limite.
Nell'interfaccia gcloud selezioniamo il nostro progetto Firebase, scegliamo l'opzione di menu principale "Catalogo" e aggiungiamo Cloud Testing API e Cloud Tools Result API.

Poi passiamo all'opzione di menu "IAM e amministrazione" -> Account di servizio -> Crea un account di servizio. Concediamo diritti di modifica del progetto.

Creiamo una chiave API in formato JSON.

Il JSON scaricato ci servirà più tardi, per ora consideriamo la configurazione di Test Lab completata.
5. Configurazione di CircleCI
Sorgevole è la domanda: cosa fare con le password? Il meccanismo delle variabili d'ambiente della nostra macchina di build ci aiuterà a mantenere al sicuro le nostre password e altri dati sensibili. Nelle impostazioni del progetto CircleCI selezioniamo Variabili d'ambiente.

E creiamo le seguenti variabili:
- chiave: GOOGLE_APPLICATION_CREDENTIALS
valore: contenuto del file json della chiave del servizio account gcloud - chiave: MATCH_PASSWORD
valore: password per decriptare il repository GitHub con i certificati - chiave: FASTLANE_PASSWORD
valore: password dell'account infrastrutturale Apple Developer Portal
Salviamo le modifiche, creiamo una PR e inviamo per la revisione al nostro team leader.
Risultati
Come risultato di queste semplici operazioni, abbiamo ottenuto un buon ambiente di test funzionante in modo stabile, con la possibilità di registrare video dello schermo del dispositivo durante il testing. Nell'esempio di test ho specificato il modello di dispositivo iPhone X, ma la farm offre una vasta scelta di combinazioni di modelli e versioni di iOS.
La seconda parte sarà dedicata alla configurazione passo-passo di Firebase Test Lab per il progetto Android.
Fonte: habr.com
