Le attività fungono da contenitori per ogni interazione utente all'interno dell'app, quindi è importante testare il comportamento delle attività dell'app durante gli eventi a livello di dispositivo come i seguenti:
- Un'altra app, ad esempio l'app Telefono del dispositivo, interrompe l'attività della tua app.
- Il sistema distrugge e ricrea la tua attività.
- L'utente inserisce la tua 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à della tua app di mantenere l'integrità dei dati e una buona esperienza utente man mano che le attività dell'app passano attraverso diversi stati nei loro cicli di vita.
Gestire lo stato di un'attività
Un aspetto fondamentale del test delle attività della tua app consiste nel posizionarle in stati particolari. Per definire la parte "dato" dei test, utilizza
istanze di ActivityScenario,
che fa parte della
libreria AndroidX Test. Utilizzando questa classe, puoi
inserire la tua attività in stati che simulano eventi a livello di dispositivo.
ActivityScenario è un'API multipiattaforma che puoi utilizzare nei test delle unità locali
e nei test di integrazione sul dispositivo. Su un dispositivo reale o virtuale,
ActivityScenario fornisce la sicurezza dei thread, 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 sposta nello stato
RESUMED. Questo stato indica che la tua attività è in esecuzione ed è
visibile agli utenti. In questo stato, puoi interagire liberamente con gli elementi
View della tua attività utilizzando i test dell'interfaccia utente Espresso.
Google consiglia di chiamare close sull'attività al termine del test. In questo modo, le risorse associate vengono pulite e la stabilità dei test migliora. ActivityScenario implementa Closeable, quindi puoi
applicare l'estensione use o try-with-resources nel linguaggio di programmazione Java, in modo che l'attività si chiuda automaticamente.
In alternativa, puoi utilizzare ActivityScenarioRule per chiamare automaticamente
ActivityScenario.launch prima di ogni test e ActivityScenario.close
al termine del test. L'esempio seguente mostra come definire una regola e ottenere un'istanza di uno scenario:
@RunWith(AndroidJUnit4::class) class MyTestSuite { @get:Rule var activityScenarioRule = activityScenarioRule<MyActivity>() @Test fun testEvent() { val scenario = activityScenarioRule.scenario } }
Portare l'attività a un nuovo stato
Per spostare l'attività in un altro stato, ad esempio CREATED o STARTED, chiama
moveToState(). Questa azione simula una situazione in cui la tua attività viene
interrotta 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 dell'attività corrente
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 illustrato 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 } } }
Ricrea l'attività
Quando le risorse di un dispositivo sono scarse, il sistema potrebbe eliminare un'attività,
richiedendo alla tua app di ricrearla quando l'utente torna nell'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
qualsiasi oggetto annotato utilizzando @NonConfigurationInstance. Questi oggetti vengono caricati
nella nuova istanza dell'attività in fase di test.
Recuperare i risultati dell'attività
Per ottenere il codice risultato o i dati associati a un'attività completata, ottieni il
valore del campo result all'interno dell'oggetto ActivityScenario, come mostrato
nel seguente snippet di codice:
@RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testResult() { launchActivity<MyActivity>().use { onView(withId(R.id.finish_button)).perform(click()) // Activity under test is now finished. val resultCode = scenario.result.resultCode val resultData = scenario.result.resultData } } }
Azioni di attivazione nell'attività
Tutti i metodi all'interno di ActivityScenario sono chiamate di blocco, quindi l'API richiede
di eseguirli nel thread di strumentazione.
Per attivare le azioni nell'attività in fase di test, utilizza i matcher di visualizzazione Espresso per interagire con gli elementi nella visualizzazione:
@RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testEvent() { launchActivity<MyActivity>().use { onView(withId(R.id.refresh)).perform(click()) } } }
Se devi chiamare un metodo sull'attività stessa, puoi farlo
in modo sicuro implementando ActivityAction:
@RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testEvent() { launchActivity<MyActivity>().use { scenario -> scenario.onActivity { activity -> activity.handleSwipeToRefresh() } } } }