Quando si progetta la strategia di test per un elemento o un sistema, ci sono tre aspetti dei test correlati:
- Ambito: quanta parte del codice tocca il test? I test consentono di verificare una singola l'intera applicazione o una via di mezzo. La l'ambito testato è in corso di test e in genere viene indicato come Oggetto Test, anche lo stato Sistema in fase di test o Unità in fase di test.
- Velocità: quanto è veloce il test? Le velocità di test possono variare da millisecondi diversi minuti.
- Fedeltà: come è "reale" il test? Ad esempio, se parte del codice per effettuare una richiesta di rete, il codice di test effettua questa richiesta di rete o il risultato non è falso? Se il test dà esito positivo con la rete, ciò significa che ha una maggiore fedeltà. Lo svantaggio è che l'esecuzione del test potrebbe richiedere più tempo, causare errori se la rete non è disponibile oppure potrebbe essere costoso da utilizzare.
Scopri cosa testare per scoprire come iniziare a definire la tua strategia di test.
Isolamento e dipendenze
Quando testi un elemento o un sistema di elementi, lo fai isolando. Per Ad esempio, per testare un ViewModel non è necessario avviare un emulatore e avviare una UI perché non dipende (o non dovrebbe) dipendere dal framework Android.
Tuttavia, il soggetto sottoposto a test potrebbe dipendere da altri perché funzioni. Per un'istanza ViewModel potrebbe dipendere da un repository di dati per funzionare.
Quando è necessario fornire una dipendenza a un soggetto sottoposto a test, una pratica comune consiste nel creare un oggetto test double (o oggetto test). I test doppi sono oggetti hanno l'aspetto e le funzionalità dell'app, ma vengono creati nel test per per fornire un comportamento o dati specifici. Il vantaggio principale è che le tue in modo rapido e semplice.
Tipi di test doppi
Esistono vari tipi di test doppi:
Falso | Un doppio di prova che ha un "funzionamento" implementazione della classe, ma è implementata in un modo che lo rende adatto per i test ma inadatto per la produzione.
Esempio: un database in memoria. I falsi non richiedono un framework simulato e sono leggeri. Sono preferiti. |
---|---|
Simulazione | Un doppio test che si comporta come lo programma e che ha aspettative sulle sue interazioni. Le simulazioni non supereranno i test se le loro interazioni non corrispondono ai requisiti da te definiti. A questo scopo, in genere le simulazioni vengono create con un framework di simulazione.
Esempio: verificare che un metodo in un database sia stato chiamato esattamente una volta. |
Stub | Un doppio del test che si comporta come lo programma, ma che non ha aspettative sulle sue interazioni. Di solito viene creato con un framework simulato. Per semplicità, i falsi sono da preferire agli stub. |
dummy | Un doppio di test che viene fatto passare ma non utilizzato, ad esempio se devi solo fornirlo come parametro.
Esempio: una funzione vuota passata come callback dei clic. |
Spionaggio | Un wrapper su un oggetto reale che tiene traccia anche di alcune informazioni aggiuntive, come nelle simulazioni. Di solito vengono evitati per aggiungere complessità. Le falsità o le truffe sono quindi da preferire alle spie. |
Ombre | Falsa utilizzata in Robolectric. |
Esempio di utilizzo di un falso
Supponiamo di voler eseguire il test delle unità per un ViewModel che dipende da un'interfaccia
denominato UserRepository
ed espone il nome del primo utente a una UI. Puoi
creare un falso test doppio implementando l'interfaccia e restituendo dati
e i dati di Google Cloud.
object FakeUserRepository : UserRepository {
fun getUsers() = listOf(UserAlice, UserBob)
}
val const UserAlice = User("Alice")
val const UserBob = User("Bob")
Questo UserRepository
fittizio non deve dipendere dai dati locali e remoti
le origini utilizzate dalla versione di produzione. Il file si trova nell'origine di test
impostato e non verrà distribuito con l'app di produzione.
Il seguente test verifica che ViewModel espone correttamente il primo utente alla vista.
@Test
fun viewModelA_loadsUsers_showsFirstUser() {
// Given a VM using fake data
val viewModel = ViewModelA(FakeUserRepository) // Kicks off data load on init
// Verify that the exposed data is correct
assertEquals(viewModel.firstUserName, UserAlice.name)
}
Sostituire UserRepository
con un falso è facile in un test delle unità, perché
ViewModel viene creato dal tester. Tuttavia, può essere difficile sostituire
elementi arbitrari nei test più grandi.
Sostituzione dei componenti e inserimento delle dipendenze
Quando i test non hanno alcun controllo sulla creazione dei sistemi sottoposti a test, la sostituzione dei componenti per i test doppi diventa più coinvolta e richiede dell'app in modo che segua un design testabile.
Anche i test end-to-end di grandi dimensioni possono trarre vantaggio dall'utilizzo di test doppi, come test dell'interfaccia utente con strumenti che analizza l'intero flusso di utenti nella tua app. Nella in questo caso, potresti rendere il test ermetico. Un test ermetico evita tutte le dipendenze esterne, come il recupero dei dati da internet. Questo migliora l'affidabilità e le prestazioni.
Puoi progettare l'app in modo da ottenere questa flessibilità manualmente, ma ti consigliamo di Utilizzando un framework di inserimento delle dipendenze come Hilt per sostituire i componenti. nella tua app al momento del test. Consulta la Guida al test di Hilt.
Robolettrico
Su Android, puoi utilizzare il framework Robolectric, che offre un tipo speciale di test doppio. Robolectric ti consente di eseguire i test su sulla workstation o nell'ambiente di integrazione continua. Utilizza un una JVM standard, senza emulatore o dispositivo. Simula l'inflazione delle visualizzazioni il caricamento delle risorse e altre parti del framework Android con test doppi chiamate ombre.
Robolectric è un simulatore, quindi non dovrebbe sostituire semplici test delle unità né essere utilizzato per eseguire test di compatibilità. Garantisce velocità e riduce i costi a scapito a una fedeltà inferiore in alcuni casi. Un buon approccio per i test dell'interfaccia utente consiste nel farli compatibile sia con i test robotici sia con quelli strumentati e decidere quando eseguirli a seconda della necessità di testare la funzionalità o la compatibilità. Entrambi espresso e Compose possono essere eseguiti su Robolectric.