Le attività fungono da container per ogni interazione utente all'interno dell'app, quindi è importante testare il comportamento delle attività dell'app durante gli eventi a livello di dispositivo, ad esempio:
- Un'altra app, ad esempio l'app Telefono del dispositivo, interrompe l'attività dell'app.
- Il sistema distrugge e ricrea l'attività.
- L'utente inserisce l'attività in un nuovo ambiente di finestre, ad esempio Picture in Picture (PIP) o multi-finestra.
In particolare, è importante assicurarsi che l'attività si comporti correttamente in risposta agli eventi descritti in Ciclo di vita dell'attività.
Questa guida descrive come valutare la capacità dell'app di mantenere l'integrità dei dati e una buona esperienza utente durante la transizione delle attività dell'app attraverso i diversi stati dei relativi cicli di vita.
Testare le attività in Compose
Quando testi un'app creata con Jetpack Compose, in genere utilizzi
createAndroidComposeRule per avviare l'attività e interagire con i
componenti dell'interfaccia utente.
Tuttavia, per testare gli eventi a livello di dispositivo, come le modifiche alla configurazione o l'inserimento dell'attività in background o la sua eliminazione da parte del sistema, devi manipolare direttamente il ciclo di vita dell'attività. Per farlo, utilizza il
framework ActivityScenario sottostante.
La regola di test di Compose esegue automaticamente il wrapping e la gestione di questo scenario. In questa guida, vedrai il seguente pattern utilizzato per colmare il divario tra i test dell'interfaccia utente moderna e la gestione standard del ciclo di vita:
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testEvent() {
val scenario = composeTestRule.activityRule.scenario
// ...
}
Gestire lo stato di un'attività
Un aspetto fondamentale del test delle attività dell'app è l'inserimento delle attività dell'app in stati specifici. Per definire questa parte "given" dei test, utilizza
istanze di ActivityScenario, parte della libreria di test AndroidX. Utilizzando questa classe, puoi inserire l'attività in stati che simulano eventi a livello di dispositivo.
ActivityScenario è un'API multipiattaforma che puoi utilizzare sia nei test unitari locali sia nei test di integrazione sul dispositivo. Su un dispositivo reale o virtuale, ActivityScenario fornisce la thread safety, sincronizzando gli eventi tra il thread di strumentazione del test e il thread che esegue l'attività in fase di test.
L'API è particolarmente adatta per valutare il comportamento di un'attività in fase di test quando viene eliminata o creata. Questa sezione presenta i casi d'uso più comuni associati a questa API.
Creare un'attività
Per creare l'attività in fase di test, aggiungi il codice mostrato nel seguente snippet:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use {
}
}
}
Dopo aver creato l'attività, ActivityScenario la porta allo stato RESUMED. Questo stato indica che l'attività è in esecuzione ed è visibile agli utenti. In questo stato, puoi interagire con i componenti componibili dell'attività
utilizzando le API di test di Compose.
Google consiglia di chiamare close sull'attività al termine del test.
In questo modo, le risorse associate vengono pulite e la stabilità dei test viene migliorata. ActivityScenario implementa Closeable, quindi puoi applicare l'estensione use in modo che l'attività si chiuda automaticamente.
In alternativa, puoi utilizzare createAndroidComposeRule per avviare automaticamente l'Activity prima di ogni test, gestire la pulizia e concederti l'accesso a entrambi i metodi di test dell'interfaccia utente di Compose e all'oggetto ActivityScenario sottostante. L'esempio seguente mostra come definire una regola e ottenere un'istanza di uno scenario da essa:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testEvent() {
val scenario = composeTestRule.activityRule.scenario
}
}
Portare l'attività a un nuovo stato
Per portare l'attività a un altro stato, ad esempio CREATED o STARTED, chiama moveToState. Questa azione simula una situazione in cui l'attività viene arrestata o messa in pausa, rispettivamente, perché viene interrotta da un'altra app o da un'azione di sistema.
Un esempio di utilizzo di moveToState è riportato nel seguente snippet di codice:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.moveToState(State.CREATED)
}
}
}
Determinare lo stato attuale dell'attività
Per determinare lo stato attuale di un'attività in fase di test, recupera il valore del campo state all'interno dell'oggetto ActivityScenario. È particolarmente utile controllare lo stato di un'attività in fase di test se l'attività reindirizza a un'altra attività o termina autonomamente, come mostrato nel seguente snippet di codice:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.onActivity { activity ->
startActivity(Intent(activity, MyOtherActivity::class.java))
}
val originalActivityState = scenario.state
}
}
}
Ricreare l'attività
Quando le risorse di un dispositivo sono scarse, il sistema potrebbe eliminare un'attività, richiedendo all'app di ricrearla quando l'utente torna all'app. Per simulare queste condizioni, chiama recreate:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.recreate()
}
}
}
La classe ActivityScenario mantiene lo stato dell'istanza salvata dell'attività e tutti gli oggetti annotati utilizzando @NonConfigurationInstance. Questi oggetti vengono caricati nella nuova istanza dell'attività in fase di test.
Recuperare i risultati dell'attività
Per recuperare il codice del risultato o i dati associati a un'attività completata, recupera il valore del campo result all'interno dell'oggetto ActivityScenario. Utilizzando createAndroidComposeRule, puoi attivare facilmente l'azione dell'interfaccia utente che completa l'attività, come mostrato nel seguente snippet di codice:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testResult() {
composeTestRule.onNodeWithTag("finish_button").performClick()
val scenario = composeTestRule.activityRule.scenario
val resultCode = scenario.result.resultCode
val resultData = scenario.result.resultData
}
}
Attivare le azioni nell'attività
Tutti i metodi all'interno di ActivityScenario sono chiamate bloccanti, quindi l'API richiede di eseguirli nel thread di strumentazione.
Per attivare le azioni nell'attività in fase di test, utilizza le API di test di Compose per interagire con i componenti componibili:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testEvent() {
composeTestRule.onNodeWithText("Refresh").performClick()
}
}
Se devi chiamare un metodo sull'attività stessa, puoi farlo in sicurezza utilizzando onActivity:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.onActivity { activity ->
activity.handleSwipeToRefresh()
}
}
}
}
Risorse aggiuntive
Per ulteriori informazioni sui test, consulta le seguenti risorse aggiuntive: