Automatizzare i test dell'interfaccia utente

Il test delle interazioni degli utenti consente di assicurarsi che gli utenti non riscontrino risultati imprevisti o abbiano un'esperienza negativa durante l'interazione con l'app. Dovresti abituarti a creare test dell'interfaccia utente (UI) se devi verificare che l'UI della tua app funzioni correttamente.

Un approccio ai test dell'interfaccia utente consiste semplicemente nel chiedere a un tester umano di eseguire una serie di operazioni utente sull'app di destinazione e verificare che funzioni correttamente. Tuttavia, questo approccio manuale può richiedere molto tempo ed essere soggetto a errori. Un approccio più efficace consiste nel scrivere i test dell'interfaccia utente in modo che le azioni degli utenti vengano eseguite in modo automatico. L'approccio automatizzato consente di eseguire i test in modo rapido e affidabile in modo ripetibile.

I test della UI avviano un'app (o una sua parte), simulano le interazioni degli utenti e, infine, verificano che l'app abbia reagito correttamente. Si tratta di test di integrazione che possono andare dalla verifica del comportamento di un piccolo componente a un test di navigazione di grandi dimensioni che attraversa un intero flusso di utenti. Sono utili per verificare le regressioni e per verificare la compatibilità con diversi livelli API e dispositivi fisici.

Test strumentali dell'interfaccia utente in Android Studio

Per eseguire test strumentati dell'interfaccia utente usando Android Studio, devi implementare il codice di test in una cartella di test Android separata: src/androidTest/java. Il plug-in Android per Gradle crea un'app di test in base al codice di test, quindi carica l'app di test sullo stesso dispositivo dell'app di destinazione. Nel codice di test puoi utilizzare framework di test dell'interfaccia utente per simulare le interazioni degli utenti nell'app di destinazione, in modo da eseguire attività di test relative a scenari di utilizzo specifici.

Framework Jetpack

Jetpack include vari framework che forniscono API per la scrittura di test dell'interfaccia utente:

  • Il framework di test Espresso (Android 4.0.1, livello API 14 o superiore) fornisce API per la scrittura di test dell'interfaccia utente per simulare le interazioni degli utenti con gli elementi View all'interno di una singola app di destinazione. Uno dei principali vantaggi dell'utilizzo di Espresso è la sincronizzazione automatica delle azioni di test con l'interfaccia utente dell'app che stai testando. Espresso rileva quando il thread principale è inattivo, quindi è in grado di eseguire i comandi di test al momento opportuno, migliorando l'affidabilità dei test.
  • Jetpack Compose (Android 5.0, livello API 21 o versioni successive) fornisce un insieme di API di test per avviare e interagire con le schermate e i componenti di Compose. Le interazioni con gli elementi Compose sono sincronizzate con i test e hanno il controllo completo su tempo, animazioni e ricomposizioni.
  • UI Automator (Android 4.3, livello API 18 o versioni successive) è un framework di test dell'interfaccia utente adatto per i test funzionali dell'interfaccia utente su più app su app di sistema e installate. Le API UI Automator ti consentono di eseguire operazioni come l'apertura del menu Impostazioni o di Avvio applicazioni su un dispositivo di test.
  • Robolectric (Android 4.1, livello API 16 o versioni successive) consente di creare test locali che vengono eseguiti sulla workstation o sull'ambiente di integrazione continua in una JVM standard, anziché su un emulatore o un dispositivo. Può usare le API Espresso o Compose di test per interagire con i componenti della UI.

Instabilità e sincronizzazione

La natura asincrona di applicazioni e framework per dispositivi mobili spesso rende difficile scrivere test affidabili e ripetibili. Quando viene inserito un evento utente, il framework di test deve attendere che l'app completi la reazione, ad esempio dalla modifica di una parte del testo sullo schermo alla ricostruzione completa di un'attività. Quando un test non ha un comportamento deterministico, è instabile.

I framework moderni come Compose o Espresso sono progettati pensando ai test, quindi c'è una certa garanzia che l'interfaccia utente sia inattiva prima della successiva azione o asserzione di test. Si tratta della sincronizzazione.

Testa sincronizzazione

Possono comunque verificarsi dei problemi quando esegui operazioni asincrone o in background sconosciute al test, ad esempio il caricamento dei dati da un database o la visualizzazione di animazioni infinite.

diagramma di flusso che mostra un ciclo che verifica se l'app è inattiva prima di superare il test
Figura 1: sincronizzazione dei test.

Per aumentare l'affidabilità della tua suite di test, puoi installare un modo per monitorare le operazioni in background, ad esempio Risorse inattive per Espresso. Inoltre, puoi sostituire i moduli per le versioni di test su cui puoi eseguire query per inattività o che migliorano la sincronizzazione, ad esempio TestDispatcher per le coroutine o RxIdler per RxJava.

Diagramma che mostra un errore di test quando la sincronizzazione si basa sull'attesa per un periodo di tempo fisso
Figura 2: l'uso del sonno nei test genera test lenti o instabili.

Architettura e configurazione dei test

L'architettura della tua app dovrebbe consentire ai test di sostituirne alcune parti per eseguire test di doppi. Inoltre, devi utilizzare librerie che forniscono utilità per facilitare i test. Ad esempio, puoi sostituire un modulo del repository di dati con una versione in memoria che fornisce dati falsi e deterministici al test.

Produzione e test di diagrammi dell'architettura. Il diagramma di produzione mostra le origini dati locali e remote che forniscono dati al repository, che a sua volta li fornisce in modo asincrono alla UI. Il diagramma di test mostra un repository Fake che fornisce i dati in modo sincrono alla UI.
Figura 3: test di una UI sostituendo le sue dipendenze con falsi.

L'approccio consigliato per abilitare questa funzionalità prevede l'inserimento delle dipendenze. Puoi creare il tuo sistema manualmente, ma ti consigliamo di utilizzare un framework DI come Hilt.

Perché eseguire il test automatico?

Un'app Android può avere come target migliaia di dispositivi diversi con diversi livelli di API e fattori di forma e l'elevato livello di personalizzazione offerto dal sistema operativo all'utente potrebbe causare il rendering errato dell'app o persino arrestarsi in modo anomalo su alcuni dispositivi.

I test dell'interfaccia utente consentono di eseguire test di compatibilità, verificando il comportamento di un'app in contesti diversi. Ti consigliamo di eseguire i test dell'interfaccia utente su dispositivi che variano nei seguenti modi:

  • Livello API: 21, 25 e 30.
  • Lingua: inglese, arabo e cinese.
  • Orientamento: verticale, orizzontale.

Inoltre, le app devono controllare il comportamento al di fuori dei telefoni. Dovresti eseguire il test su tablet, pieghevoli e altri dispositivi.

Risorse aggiuntive

Per saperne di più sulla creazione dei test dell'interfaccia utente, consulta le risorse seguenti.

Documentazione

Codelab