Introduzione al test di iOS con l'automazione dell'interfaccia utente

Immagina di essere in grado di scrivere script che interagiscono automaticamente con la tua applicazione iOS e di verificare i risultati. È possibile con l'automazione dell'interfaccia utente. UI Automation è uno strumento fornito da Apple per eseguire un livello più alto di test sulla tua applicazione iOS oltre qualsiasi risultato raggiungibile con XCTest.

1. White Box contro Black Box Testing

Potresti aver sentito il paragone tra i test della scatola bianca e quelli della scatola nera riguardo a come si potrebbe testare un pezzo di software. Se non hai familiarità con questi concetti, lascia che ti spieghi come funzionano.

Test della scatola bianca

Immagina che ci sia un pezzo di software in esecuzione all'interno di una scatola. Con il test della scatola bianca, puoi vedere all'interno della scatola e osservare tutti i pezzi grintosi di come funziona il software, e quindi prendere decisioni istruite su come testare il software. Puoi anche avere hook di livello più profondo nel software dai test che scrivi.

Il test dell'unità è il test della scatola bianca. Durante la scrittura dei test unitari, il tester ha accesso a grana fine al codice sotto test. Il tester può effettivamente scrivere test che sfruttano il software in prova al metodo, o unità, livello.

Nello sviluppo del software iOS utilizziamo il XCTest quadro per eseguire questo tipo di test. Dai un'occhiata ad un altro tutorial che ho scritto su come iniziare con XCTest.

Black Box Testing

Nel test della scatola nera, la scatola è opaca. Il tester non può vedere all'interno della scatola. Il tester non può accedere e non conosce l'implementazione del codice di base per scrivere test. Invece, il tester è costretto a utilizzare l'applicazione come 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 passaggi predefiniti e verifica visivamente i risultati.
  • Utilizza strumenti specializzati per testare l'applicazione con API che si comportano in modo simile a come un umano interagisce.

Nello sviluppo di applicazioni iOS, Apple fornisce uno strumento chiamato Automazione dell'interfaccia utente per eseguire il test della scatola nera.

2. Che cos'è l'automazione UI? 

UI Automation è uno strumento che Apple fornisce e mantiene per test automatici, di livello superiore, su applicazioni iOS. I test sono scritti in JavaScript, aderendo ad una API definita da Apple.

È possibile semplificare i test di scrittura facendo affidamento sulle etichette di accessibilità per gli elementi dell'interfaccia utente nell'applicazione. Non preoccuparti però, se non li hai definiti, ci sono alternative disponibili.

L'API di automazione interfaccia utente manca del tipico formato basato su xUnit per la scrittura di test. Una differenza con il test delle unità è che il tester deve registrare manualmente il successo e gli errori. I test di automazione dell'interfaccia utente vengono eseguiti dallo strumento di automazione all'interno di strumenti strumento che viene fornito con gli strumenti di sviluppo di Apple. I test possono essere eseguiti su iOS Simulator o su un dispositivo fisico.

3. Scrittura di test di automazione dell'interfaccia utente

Passaggio 1: aprire il progetto di esempio

Ho aggiornato il progetto di esempio utilizzato nel precedente tutorial sui test di iOS con alcuni elementi aggiuntivi dell'interfaccia utente che forniscono alcuni ganci utili per l'aggiunta di test di automazione dell'interfaccia utente. Scarica il progetto da GitHub. Aprire il progetto ed eseguire l'applicazione per assicurarsi che tutto funzioni come previsto. Dovresti vedere un'interfaccia utente simile a quella mostrata sotto.


Prima di scrivere qualsiasi test, sentiti libero di provare l'applicazione di esempio per familiarizzare con la sua 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 immessa.

Passaggio 2: creare un test di automazione dell'interfaccia utente

Ora che hai familiarità con l'applicazione di esempio, è giunto il momento di aggiungere un test di automazione interfaccia utente. UI Automation è uno strumento che può essere trovato in strumenti. Per eseguire l'applicazione di esempio in Strumenti, selezionare Prodotto> Profilo dal menu di Xcode. Selezionare Automazione dalla lista degli strumenti.


La finestra principale degli strumenti si aprirà con un unico strumento pronto per essere eseguito, lo strumento di automazione (lo strumento di automazione esegue i casi di test dell'interfaccia utente). Vedrai anche un'area nella metà inferiore della finestra che sembra un editor di testo. Questo è l'editor di script. Qui è dove scriverete i vostri test di automazione dell'interfaccia utente. Per questo primo test, segui le istruzioni di seguito, 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 () ["Campo input"];

Imposta il valore del campo di testo.

inputField.setValue ( "ciao”);

Verificare che il valore sia stato impostato correttamente e, in caso affermativo, superare il test. Fallire il test se non lo fosse.

if (inputField.value ()! = "hi") UIALogger.logFail ("Il campo di immissione NON poteva essere impostato con la stringa!"); else UIALogger.logPass ("Il campo di immissione è stato possibile impostare con la stringa!");

Mentre questo test è abbastanza banale, ha un valore. Abbiamo appena scritto un test che verifica la presenza di un campo di testo all'avvio dell'applicazione e che verifica se una stringa casuale può essere impostata come valore del campo di testo. Se non mi credi, rimuovi il campo di testo dallo storyboard ed esegui il test. Vedrai che fallisce.

Questo test dimostra tre importanti parti di scrittura dei test di UI Automation. In primo luogo, mostra come accedere a un elemento semplice dell'interfaccia utente, il campo di testo. In particolare, accediamo a un dizionario di tutti i campi di testo nella vista di base dell'applicazione tramite target.frontMostApp (). MainWindow (). textfields () e poi troviamo il campo di testo a cui siamo interessati cercando quello con la chiave Campo di inserimento. Questa chiave è in realtà l'etichetta di accessibilità del campo di testo. In questo caso, è definito nello storyboard. Possiamo anche impostare l'etichetta di accessibilità nel codice usando il accessibilityLabel proprietà su NSObject.

L'accesso alla finestra principale dell'applicazione, alla maggior parte delle applicazioni frontali e alla destinazione sono comuni quando si lavora con UI Automation. Ti mostrerò come renderlo più facile e meno dettagliato in questo tutorial.

Secondo, questo ti mostra che puoi interagire con gli elementi dell'interfaccia utente sullo schermo. In questo caso, impostiamo il valore del campo di testo, mimando l'utente che interagisce con l'applicazione inserendo del testo nel campo di testo.

E in terzo luogo, l'esempio mostra anche una tecnica per verificare cosa succede nell'applicazione. Se il valore viene impostato correttamente, passa il test. Se il valore non è impostato, il test fallisce.

Passaggio 3: Salvataggio dei test

Mentre scrivere i test nell'editor di script è conveniente, diventa rapidamente ingombrante e difficile da mantenere. Se esci da Strumenti, tutte le modifiche non salvate vengono eliminate. Abbiamo bisogno di salvare i test che scriviamo. Basta copiare e incollare il test in un nuovo documento nel tuo editor di testo preferito e salvarlo. Puoi trovare i test creati in questo tutorial nel progetto di esempio sotto Jumblify / JumblifyTests / AutomationTests.js.

Per eseguire il test, selezionare la scheda centrale nel riquadro a destra, accanto all'editor degli script, quindi selezionare Aggiungi> Importa.


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

Passaggio 4: toccare un pulsante

Aggiorniamo il nostro test per testare l'interazione con il pulsante. Il nostro test aggiunge già del testo al campo di testo, quindi è sufficiente aggiungere il codice per toccare il pulsante. Consideriamo innanzitutto come trovare il pulsante nella vista in modo che possa essere TAPpato. Ci sono almeno tre modi per farlo e ogni approccio ha i suoi compromessi.

Approccio 1

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

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

Naturalmente, non ho idea se quelle siano anche le coordinate del pulsante sullo schermo e non mi preoccuperò di questo, perché questo approccio non è lo strumento giusto per questo lavoro. Sto solo menzionandolo così sai che esiste. Usando il rubinetto metodo attivo bersaglio toccare un pulsante è soggetto ad errori, perché quel pulsante potrebbe non essere sempre in quella specifica coordinata.

Approccio 2

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

pulsanti target.frontMostApp () MainWindow () () [0] .tap ()..;

Questo approccio è un po 'meglio. Non stiamo codificando una coordinata, ma stiamo codificando con fatica un indice di array per trovare il pulsante. Se ci capita di aggiungere un altro pulsante sulla pagina, potrebbe accidentalmente interrompere questo test.

Approccio 3

Questo mi porta al terzo modo per trovare il pulsante sulla pagina, usando le etichette di accessibilità. Usando un'etichetta di accessibilità, possiamo accedere direttamente al pulsante, semplicemente ci piacerebbe trovare un oggetto in un dizionario usando una chiave.

target.frontMostApp (). mainWindow (). buttons () ["Jumblify Button"]. tap ();

Tuttavia, se aggiungi la riga sopra allo script e la esegui, riceverai un errore.


Questo perché non abbiamo ancora definito l'etichetta di accessibilità per il pulsante. Per farlo, passa a Xcode e apri lo storyboard del progetto. Trova il pulsante nella vista e apri il pulsante Identity Inspector sulla destra (Visualizza> Utilità> Identity Inspector). Assicurarsi che Accessibilità è abilitato e imposta il Etichetta per il pulsante a Pulsante Jumblify.


Per eseguire nuovamente il test, è necessario eseguire l'applicazione da Xcode selezionando Prodotto > Correre e quindi tracciare nuovamente l'applicazione selezionando Prodotto > Profilo. Questo esegue i test e ogni test dovrebbe passare ora.

Passaggio 5: verifica la stringa jumbled 

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 è popolato con la stringa corretta, abbiamo bisogno di 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 nell'applicazione per fare un'asserzione su di esso.

Esiste un metodo su quasi tutti gli oggetti nell'API di automazione interfaccia utente, logElementTree. Questo metodo registra gli elementi nidificati di un determinato 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. Dai un'occhiata alla seguente riga di codice.

target.frontMostApp () MainWindow () logElementTree ()..;

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


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

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

var stringResult = target.frontMostApp (). mainWindow (). staticTexts () ["ih"]; if (! stringResult.isValid ()) UIALogger.logFail ("Il testo di output NON è stato impostato con la stringa correttamente invertita!"); else UIALogger.logPass ("Il testo di output è stato impostato con la stringa invertita correttamente!");

4. Scratching the Surface

Ci sono tanti altri modi in cui un utente finale può interagire con un dispositivo iOS mentre usa la tua app. Ciò significa che ci sono molti altri modi in cui è possibile utilizzare l'automazione dell'interfaccia utente per simulare queste interazioni. Piuttosto che tentare di acquisire un elenco completo di queste interazioni, ti indirizzerò alla documentazione di riferimento sull'interfaccia utente.

Per ogni tipo di oggetto con cui è possibile interagire, è possibile visualizzare l'elenco di metodi disponibili su quell'oggetto. Alcuni metodi sono per il recupero degli attributi sull'oggetto mentre altri sono per simulare l'interazione tattile, come ad esempio flickInsideWithOptions sopra UIAWindow.

Registrazione di una sessione

Mentre provi a testare app sempre più complicate con UI Automation, scoprirai che a volte è piuttosto noioso da usare ripetutamente logElementTree per trovare l'elemento che stai cercando. Ciò diventa anche noioso e complesso per le applicazioni con una gerarchia di visualizzazione complessa o la navigazione. In questi casi, puoi utilizzare un'altra funzionalità di strumenti per registrare un insieme di interazioni dell'utente. Ciò che è ancora più interessante è che Instruments genera il codice JavaScript di automazione interfaccia utente necessario per riprodurre le interazioni registrate. Ecco come puoi provarlo per te.

In Strumenti e con lo strumento di automazione selezionato, cerca il pulsante di registrazione nella parte inferiore della finestra.


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


Instruments avvierà la tua applicazione in iOS Simulator e sarai in grado di interagire con essa. Gli strumenti genereranno uno script basato sulle tue interazioni in tempo reale. Provaci. Ruota il simulatore iOS, tocca le posizioni casuali, esegui un gesto di scorrimento, ecc. È un modo davvero utile per esplorare le possibilità di automazione dell'interfaccia utente.

Evitare una base di codice monolitico

Come probabilmente puoi prevedere, se continuiamo ad aggiungere più 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: Ciò implica che i test che scriviamo devono essere focalizzati su una specifica funzionalità. Gli darò anche un nome appropriato, come ad esempio testEmptyInputField.
  • Test relativi al gruppo in un unico file: Ho anche raggruppato test correlati nello stesso file. Ciò mantiene il codice in un file gestibile. Ciò rende anche più facile testare parti separate di funzionalità eseguendo i test in un file specifico. Inoltre, è possibile creare uno script principale in cui si chiamano le funzioni oi test che sono stati raggruppati in altri file di test.

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

#import "OtherTests.js"

Conclusione

In questo tutorial, hai appreso il valore dei test di livello superiore e in che modo l'automazione dell'interfaccia utente può aiutare a colmare questa lacuna. È un altro strumento nella tua casella degli strumenti per aiutarti a spedire applicazioni affidabili e robuste.

Riferimenti

Riferimento JavaScript di automazione interfaccia utente