Introduzione ai test iOS con UI Automation

Apr 17, 2021
admin

Immaginate di poter scrivere degli script che interagiscono automaticamente con la vostra applicazione iOS e di poterne verificare i risultati. Con UI Automation è possibile. UI Automation è uno strumento fornito da Apple per eseguire un livello superiore di test sulla vostra applicazione iOS, oltre a quello ottenibile con XCTest.

1. White Box versus Black Box Testing

Potreste aver sentito il confronto tra white box testing e black box testing per quanto riguarda il modo in cui si può testare un pezzo di software. Se non hai familiarità con questi concetti, lascia che ti spieghi come funzionano.

White Box Testing

Immagina che ci sia un pezzo di software che gira dentro una scatola. Con i test in scatola bianca, si può vedere all’interno della scatola e guardare tutti i pezzi del funzionamento del software, e poi prendere decisioni istruite su come testare il software. Si possono anche avere agganci di livello più profondo nel software dai test che si scrivono.

I test delle unità sono test in scatola bianca. Quando si scrivono i test unitari, il tester ha un accesso a grana fine al codice sotto test. Il tester può effettivamente scrivere test che sfruttano il software sotto test a livello di metodo, o di unità.

Nello sviluppo di software iOS usiamo il framework XCTest per eseguire questo tipo di test. Dai un’occhiata a un altro tutorial che ho scritto su come iniziare con XCTest.

Black Box Testing

Nel black box testing, la scatola è opaca. Il tester non può vedere dentro la scatola. Il tester non può accedere e non conosce l’implementazione del codice base per scrivere i test. Invece, il tester è costretto a usare l’applicazione come farebbe un utente finale, interagendo con l’applicazione e aspettando la sua risposta, verificando i risultati.

Ci sono almeno due modi per eseguire questo tipo di test.

  • Un tester che esegue ripetutamente e manualmente una serie di passi predefiniti e verifica visivamente i risultati.
  • Utilizza strumenti specializzati per testare l’applicazione con API che si comportano in modo simile a come interagisce un essere umano.

Nello sviluppo di applicazioni iOS, Apple fornisce uno strumento chiamato UI Automation per eseguire test in scatola nera.

2. Che cos’è UI Automation?

UI Automation è uno strumento che Apple fornisce e mantiene per i test automatizzati di livello superiore delle applicazioni iOS. I test sono scritti in JavaScript, aderendo a un’API definita da Apple.

La scrittura dei test può essere resa più facile affidandosi alle etichette di accessibilità per gli elementi dell’interfaccia utente nella vostra applicazione. Non preoccupatevi però, se non le avete definite, ci sono alternative disponibili.

La UI Automation API manca del tipico formato basato su xUnit per scrivere i test. Una differenza con i test unitari è che il tester ha bisogno di registrare manualmente successi e fallimenti. I test di UI Automation sono eseguiti dallo strumento Automation all’interno dello strumento Instruments che viene fornito con gli strumenti di sviluppo di Apple. I test possono essere eseguiti nel simulatore iOS o su un dispositivo fisico.

3. Scrivere test di automazione UI

Passo 1: Aprire il progetto di esempio

Ho aggiornato il progetto di esempio utilizzato nel precedente tutorial sui test iOS con alcuni elementi aggiuntivi dell’interfaccia utente che forniscono alcuni ganci utili per aggiungere test di automazione UI. Scaricate il progetto da GitHub. Aprite il progetto ed eseguite l’applicazione per assicurarvi che tutto funzioni come previsto. Dovresti vedere un’interfaccia utente simile a quella mostrata qui sotto.

Prima di scrivere qualsiasi test, sentiti libero di provare l’applicazione di esempio per familiarizzare con le sue funzionalità. Come utente, puoi inserire del testo nel campo di testo e toccare il pulsante per vedere un’etichetta sullo schermo che mostra la stringa invertita e inserita.

Step 2: creare un test di automazione UI

Ora che hai familiarità con l’applicazione di esempio, è il momento di aggiungere un test di automazione UI. UI Automation è uno strumento che si trova in Instruments. Per eseguire l’applicazione di esempio in Instruments, seleziona Product > Profile dal menu di Xcode. Seleziona Automation dall’elenco degli strumenti.

La finestra principale di Instruments si aprirà con un solo strumento pronto per essere eseguito, lo strumento Automation (lo strumento Automation esegue i casi di test UI Automation). Vedrai anche un’area nella metà inferiore della finestra che sembra un editor di testo. Questo è l’editor di script. Qui è dove scriverai i tuoi test di automazione dell’interfaccia utente. Per questo primo test, segui le seguenti istruzioni, aggiungendo ogni riga allo script nell’editor di script.

Inizia memorizzando un riferimento al campo di testo in una variabile.

var inputField = target.frontMostApp().mainWindow().textFields();

Imposta il valore del campo di testo.

inputField.setValue("hi");

Verifica che il valore sia stato impostato con successo e, se è così, passa il test. Fallisci il test se non lo è stato.

Anche se questo test è abbastanza banale, ha un valore. Abbiamo appena scritto un test che verifica la presenza di un campo di testo quando l’applicazione viene lanciata e che verifica se una stringa casuale può essere impostata come valore del campo di testo. Se non mi credete, rimuovete il campo di testo dallo storyboard ed eseguite il test. Vedrete che fallisce.

Questo test dimostra tre parti importanti della scrittura di test di automazione UI. In primo luogo, mostra come accedere a un semplice elemento dell’interfaccia utente, il campo di testo. In particolare, accediamo a un dizionario di tutti i campi di testo nella vista base dell’applicazione tramite target.frontMostApp().mainWindow().textFields() e poi troviamo il campo di testo che ci interessa cercando quello con la chiave Input Field. Questa chiave è in realtà l’etichetta di accessibilità del campo di testo. In questo caso, è definita nello storyboard. Possiamo anche impostare l’etichetta di accessibilità nel codice usando la proprietà accessibilityLabel su NSObject.

L’accesso alla finestra principale dell’applicazione, l’applicazione principale e l’obiettivo sono comuni quando si lavora con UI Automation. Vi mostrerò come rendere questo più facile e meno verboso più avanti in questo tutorial.

In secondo luogo, questo vi mostra che potete interagire con gli elementi dell’interfaccia utente sullo schermo. In questo caso, impostiamo il valore del campo di testo, imitando l’utente che interagisce con l’applicazione inserendo del testo nel campo di testo.

In terzo luogo, l’esempio mostra anche una tecnica per verificare cosa succede nell’applicazione. Se il valore viene impostato con successo, il test passa. Se il valore non è impostato, il test fallisce.

Step 3: Salvare i test

Sebbene scrivere test nell’editor di script sia comodo, diventa rapidamente ingombrante e difficile da mantenere. Se si esce da Instruments, tutte le modifiche non salvate vengono scartate. Abbiamo bisogno di salvare i test che scriviamo. Semplicemente copiate e incollate il vostro test in un nuovo documento nel vostro editor di testo preferito e salvatelo. Puoi trovare i test creati in questo tutorial nel progetto di esempio sotto Jumblify/JumblifyTests/AutomationTests.js.

Per eseguire il test, seleziona la scheda centrale nel pannello a destra, accanto all’editor di script, e seleziona Add > Import.

Ti verrà richiesto di selezionare lo script da importare. Naviga fino allo script salvato e importalo. Puoi ancora cambiare lo script nell’editor di script. Qualsiasi modifica verrà salvata automaticamente nel file esterno che hai creato.

Passo 4: Toccare un pulsante

Aggiorniamo il nostro test per verificare l’interazione con il pulsante. Il nostro test aggiunge già del testo al campo di testo, quindi abbiamo solo bisogno di aggiungere del codice per toccare il pulsante. Consideriamo prima come trovare il pulsante nella vista in modo che possa essere toccato. Ci sono almeno tre modi per farlo e ogni approccio ha i suoi compromessi.

Approccio 1

Possiamo programmaticamente toccare una coordinata (X, Y) sullo schermo. Lo facciamo con la seguente linea di codice:

target.tap({x: 8.00, y: 50.00});

Ovviamente, non ho idea se quelle siano le coordinate del pulsante sullo schermo e non me ne preoccupo, perché questo approccio non è lo strumento giusto per questo lavoro. Lo menziono solo per farvi sapere che esiste. Usare il metodo tap su target per toccare un pulsante è soggetto a errori, perché quel pulsante potrebbe non essere sempre a quella specifica coordinata.

Approccio 2

È anche possibile trovare il pulsante cercando nell’array di pulsanti della finestra principale, in modo simile a come abbiamo avuto accesso al campo di testo nel primo test. Invece di accedere direttamente al pulsante usando una chiave, possiamo recuperare un array di pulsanti della finestra principale e codificare un indice di array per ottenere un riferimento al pulsante.

target.frontMostApp().mainWindow().buttons().tap();

Questo approccio è leggermente migliore. Non stiamo codificando una coordinata, ma stiamo codificando un indice di array per trovare il pulsante. Se ci capita di aggiungere un altro pulsante nella pagina, potrebbe accidentalmente rompere questo test.

Approccio 3

Questo mi porta al terzo modo per trovare il pulsante nella pagina, usando le etichette di accessibilità. Usando un’etichetta di accessibilità, possiamo accedere direttamente al pulsante proprio come troveremmo un oggetto in un dizionario usando una chiave.

target.frontMostApp().mainWindow().buttons().tap();

Tuttavia, se aggiungete la linea precedente allo script e lo eseguite, otterrete un errore.

Questo perché non abbiamo ancora definito l’etichetta di accessibilità per il pulsante. Per farlo, passate a Xcode e aprite lo storyboard del progetto. Trova il pulsante nella vista e apri l’Ispettore identità sulla destra (View > Utilities > Identity Inspector). Assicurati che l’accessibilità sia abilitata e imposta l’etichetta del pulsante su Jumblify Button.

Per eseguire nuovamente il test, dovrai eseguire l’applicazione da Xcode selezionando Product > Run e poi profilare nuovamente l’applicazione selezionando Product > Profile. Questo esegue i test e ogni test dovrebbe passare ora.

Step 5: Verificare la stringa confusa

Come ho detto prima, la nostra applicazione prende una stringa di testo come input, e, quando l’utente tocca il pulsante, visualizza la stringa invertita. Abbiamo bisogno di aggiungere un altro test per verificare che la stringa di input sia correttamente invertita. Per verificare che il UILabel sia popolato con la stringa corretta, dobbiamo capire come fare riferimento al UILabel e verificare la stringa che visualizza. Questo è un problema comune quando si scrivono i test di automazione, cioè capire come fare riferimento a un elemento dell’applicazione per fare un’asserzione su di esso.

C’è un metodo su quasi ogni oggetto nell’API di automazione UI, logElementTree. Questo metodo registra gli elementi annidati di un dato elemento. Questo è molto utile per capire la gerarchia degli elementi nell’applicazione e aiuta a capire come indirizzare un elemento specifico.

Vediamo come funziona registrando l’albero degli elementi della finestra principale. Date un’occhiata alla seguente linea di codice.

target.frontMostApp().mainWindow().logElementTree();

Aggiungendo questa linea allo script di test si ottiene il seguente output:

Come potete vedere, c’è un sottoelemento UIAStaticText del UIAWindow e potete anche vedere che ha un nome ih, che è anche la stringa inversa che dobbiamo verificare. Ora, per completare il nostro test, dobbiamo solo aggiungere del codice per accedere a questo elemento e verificare che sia presente.

Perché dobbiamo verificare solo se l’elemento UIAStaticText è presente? Poiché il nome dell’elemento è la stringa invertita della stringa di input, la verifica della sua presenza conferma che la stringa è stata correttamente invertita. Se l’elemento non esiste quando si fa riferimento al nome – la stringa invertita – allora significa che la stringa non è stata invertita correttamente.

4. Scratching the Surface

Ci sono molti altri modi in cui un utente finale può interagire con un dispositivo iOS mentre usa la vostra applicazione. Questo significa che ci sono molti altri modi in cui potete usare UI Automation per simulare queste interazioni. Piuttosto che tentare di catturare un elenco completo di queste interazioni, vi indirizzerò alla documentazione di riferimento di UI Automation.

Per ogni tipo di oggetto con cui potete interagire, potete visualizzare l’elenco dei metodi disponibili su quell’oggetto. Alcuni metodi servono a recuperare gli attributi dell’oggetto, mentre altri servono a simulare l’interazione tattile, come flickInsideWithOptions su UIAWindow.

Registrare una sessione

Tentando di testare applicazioni sempre più complicate con UI Automation, scoprirete che a volte è piuttosto noioso usare ripetutamente logElementTree per trovare l’elemento che state cercando. Questo diventa anche noioso e complesso per applicazioni con una complessa gerarchia di viste o di navigazione. In questi casi, potete usare un’altra caratteristica di Instruments per registrare una serie di interazioni dell’utente. La cosa ancora più interessante è che Instruments genera il codice JavaScript di automazione dell’interfaccia utente necessario per riprodurre le interazioni registrate. Ecco come potete provarlo voi stessi.

In Instruments e con lo strumento Automation selezionato, cercate il pulsante di registrazione nella parte inferiore della finestra.

Se cliccate sul pulsante di registrazione, Instruments avvierà una sessione di registrazione come mostrato nello screenshot qui sotto.

Instruments avvierà la vostra applicazione nel simulatore iOS e potrete interagire con essa. Instruments genererà uno script basato sulle vostre interazioni in tempo reale. Fate una prova. Ruotate il simulatore iOS, toccate in punti casuali, eseguite un gesto swipe, ecc. È un modo davvero utile per aiutare ad esplorare le possibilità dell’automazione dell’interfaccia utente.

Evitare una base di codice monolitica

Come probabilmente potete prevedere, se continuiamo ad aggiungere altri test al file di test che abbiamo creato con lo stesso metodo, diventerà rapidamente difficile da mantenere. Cosa possiamo fare per evitare che ciò accada. Nei miei test, faccio due cose per risolvere questo problema:

  • Un test per una funzione: Questo implica che i test che scriviamo devono essere focalizzati su un pezzo specifico di funzionalità. Gli do anche un nome appropriato, come testEmptyInputField.
  • Raggruppo i test correlati in un unico file: Raggruppo anche i test correlati nello stesso file. Questo mantiene il codice in un file gestibile. Questo rende anche più facile testare pezzi separati di funzionalità eseguendo i test in un file specifico. Inoltre, puoi creare uno script principale in cui chiami le funzioni o i test che hai raggruppato in altri file di test.

Nel seguente frammento di codice, importiamo un file JavaScript e questo ci rende disponibili le funzioni in quel file JavaScript.

#import "OtherTests.js"

Conclusione

In questo tutorial, hai imparato il valore dei test di livello superiore e come UI Automation può aiutarti a colmare questo vuoto. È un altro strumento nella tua cassetta degli attrezzi per assicurarti di spedire applicazioni affidabili e robuste.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.