Istruzioni

Alternative alle risorse di monitoraggio di inattività nei test di Compose: le API waitUntil (aggiornamento)

Lettura di 3 minuti
Jose Alcérreca
Developer Relations Engineer

In questo articolo imparerai a utilizzare l'API di test waitUntil in Compose per attendere che vengano soddisfatte determinate condizioni. In alcune situazioni, questa è una buona alternativa all'utilizzo di risorse inattive.

[Aggiornamento 2023] Riepilogo: utilizza le nuove API waitUntil per la sincronizzazione nei test di Compose (v1.4.0 e versioni successive).


Che cos'è la sincronizzazione?

Un modo per classificare i test è in base al loro ambito. I test di piccole dimensioni, o unit test, si concentrano su piccole parti dell'app, mentre i test di grandi dimensioni, o end-to-end, coprono una parte più ampia dell'app. Puoi leggere informazioni su questo e altri tipi di test nella documentazione sui test appena aggiornata.

Premi Invio o fai clic per visualizzare l'immagine a grandezza originale

large_0_9n_Nqkt_HHUTOQ_In_AI_b113b43bcf.png
Diversi ambiti di test in un'app

La sincronizzazione è il meccanismo che consente al test di sapere quando eseguire l'operazione successiva. Più grande è il blocco di codice che scegli di verificare, più difficile è la sincronizzazione con il test. Nei test delle unità è facile avere il pieno controllo dell'esecuzione del codice da verificare. Tuttavia, man mano che l'ambito si espande per includere più classi, moduli e livelli, diventa difficile per il framework di test sapere se l'app è nel bel mezzo di un'operazione o meno.

Premi Invio o fai clic per visualizzare l'immagine a grandezza originale

large_correct_b1a355f41b.webp
Sincronizzazione corretta tra test e app

androidx.test e, per estensione, Test di composizione, utilizzano alcuni trucchi interni per non farti preoccupare troppo di questo aspetto. Ad esempio, se il thread principale è occupato, il test si interrompe finché non può eseguire la riga successiva.

Tuttavia, non possono sapere tutto. Ad esempio, se carichi i dati in un thread in background, il framework di test potrebbe eseguire l'operazione successiva troppo presto, causando l'esito negativo del test. La situazione peggiore si verifica quando ciò accade solo una piccola percentuale di volte, rendendo il test instabile.

Opzione 1: risorse inattive

Idling Resources è una funzionalità di Espresso che consente allo sviluppatore di decidere quando l'app è occupata. Puoi utilizzarli in due modi:

1. Installarli nel framework o nella libreria che esegue un lavoro che il test non può vedere.

Un buon esempio è RxIdler, che esegue il wrapping di uno scheduler RxJava. Questo è il modo preferito per registrare le risorse di monitoraggio di inattività perché ti consente di mantenere la configurazione del test separata in modo pulito dal codice di test.

2. Modifica del codice in fase di test per esporre esplicitamente informazioni sull'attività o meno dell'app.

Ad esempio, potresti modificare il repository (o un test double) per indicare che è occupato durante il caricamento dei dati da un'origine dati:

Questa soluzione non è ideale perché inquina il codice di produzione o crea test doppi complicati e in alcune situazioni sono difficili da installare. Ad esempio, come utilizzeresti Idling Resources in un flusso Kotlin? Quale aggiornamento è quello finale?

Invece, possiamo aspettare.

Opzione 2: aspettare le cose… nel modo sbagliato

Il caricamento dei dati è in genere rapido, soprattutto quando si utilizzano dati fittizi, quindi perché perdere tempo con le risorse inattive quando puoi semplicemente mettere in pausa il test per un paio di secondi?

Questo test verrà eseguito più lentamente del necessario o non riuscirà. Quando hai centinaia o migliaia di test UI, vuoi che siano il più veloci possibile.

Inoltre, a volte gli emulatori o i dispositivi si comportano in modo anomalo e si bloccano, il che fa sì che l'operazione richieda un po' più di 2000 ms, interrompendo la build. Quando hai centinaia di test, questo diventa un problema enorme.

0_DOCdjq-JpPDGV5OB.png

Opzione 3: aspettare nel modo giusto

Se non vuoi modificare il codice in fase di test per mostrare quando è occupato, un'altra opzione è attendere che venga soddisfatta una determinata condizione, anziché attendere un periodo di tempo arbitrario.

1_jIYFxE4qlHXMi2SwW6JemA.png

In Compose, puoi utilizzare la funzione waitUntil, che accetta un'altra funzione che produce un valore booleano.

Aggiornamento del 22/03/2023: a partire da Compose 1.4.0, abbiamo aggiunto un nuovo insieme di API waitUntil:

[Prima della versione 1.4.0: utilizza questi helper: waitUntilExists, waitUntilNodeCount]

…e utilizzali in questo modo:

Utilizza queste API solo quando devi sincronizzare il test con la UI. La sincronizzazione di ogni istruzione di test contamina inutilmente il codice di test, rendendone più difficile la manutenzione.

Quando dovresti utilizzarlo? Un buon caso d'uso è il caricamento di dati da un elemento osservabile (con LiveData, Kotlin Flow o RxJava). Quando la tua UI deve ricevere più aggiornamenti prima di essere considerata inattiva, potresti voler semplificare la sincronizzazione utilizzando waitUntil.

Ad esempio, quando raccogli un flusso da una visualizzazione:

e invii più elementi:

Se repository impiega un tempo indeterminato per restituire il primo risultato, il framework di test considererà "Caricamento" lo stato di inattività (il valore iniziale assegnato in collectAsState) e continuerà con l'istruzione successiva.

Pertanto, puoi rendere il test molto più affidabile se ti assicuri che l'interfaccia utente non mostri l'indicatore di caricamento:


Buon… aspetta… test!


Licenza per gli snippet di codice:

Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0
Scritto da:

Continua a leggere