Le attività fungono da contenitori per ogni interazione utente all'interno dell'app, pertanto è importante verificare il comportamento delle attività dell'app durante eventi a livello di dispositivo, come i seguenti:
- Un'altra app, ad esempio l'app Telefono del dispositivo, interrompe l'attività dell'app.
- Il sistema distrugge e ricrea la tua attività.
- L'utente inserisce la tua attività in un nuovo ambiente a finestre, ad esempio Picture in picture (PIP) o la modalità multi-finestra.
In particolare, è importante verificare che l'attività si comporti correttamente in risposta agli eventi descritti nella sezione Il 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 durante la transizione delle attività dell'app attraverso stati diversi nei loro cicli di vita.
Controllare lo stato di un'attività
Un aspetto chiave del test delle attività della tua app consiste nel posizionare le attività dell'app in determinati stati. Per definire questa parte "data" dei tuoi test, utilizza le istanze di ActivityScenario
, che fanno parte della libreria di AndroidX Test. Utilizzando questa lezione, puoi posizionare l'attività in stati che simulano eventi a livello di dispositivo.
ActivityScenario
è un'API multipiattaforma che puoi utilizzare sia nei test delle unità locali sia nei test di integrazione on-device. Su un dispositivo reale o virtuale, ActivityScenario
offre 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 nello snippet seguente:
@RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testEvent() { launchActivity<MyActivity>().use { } } }
Dopo aver creato l'attività, ActivityScenario
la trasferisce allo stato RESUMED
. Questo stato indica che l'attività è in esecuzione ed è visibile agli utenti. In questo stato, puoi interagire con gli elementi View
della tua attività utilizzando i test della UI di Espresso.
Google consiglia di chiamare close
nell'attività al termine del test. Questo esegue la pulizia delle risorse associate e migliora la stabilità dei test. 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
durante la rimozione del test. L'esempio seguente mostra come definire una regola e ricavarne l'istanza di uno scenario:
@RunWith(AndroidJUnit4::class) class MyTestSuite { @get:Rule var activityScenarioRule = activityScenarioRule<MyActivity>() @Test fun testEvent() { val scenario = activityScenarioRule.scenario } }
Porta 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 interrotta o messa in pausa, rispettivamente, perché è stata 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, ottieni il valore del campo state
all'interno dell'oggetto ActivityScenario
. È particolarmente utile controllare lo stato di un'attività sottoposta a test se l'attività reindirizza a un'altra attività o si conclude 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 } } }
Ricrea l'attività
Quando le risorse di un dispositivo scarseggia, il sistema potrebbe distruggere 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 di un'attività
Per ottenere il codice risultato o i dati associati a un'attività terminata, 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 } } }
Attiva azioni nell'attività
Tutti i metodi all'interno di ActivityScenario
bloccano le chiamate, quindi l'API richiede che tu le esegua nel thread della strumentazione.
Per attivare le azioni nell'attività sottoposta a test, utilizza i matcher della vista Espresso per interagire con gli elementi della vista:
@RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testEvent() { launchActivity<MyActivity>().use { onView(withId(R.id.refresh)).perform(click()) } } }
Tuttavia, se devi chiamare un metodo sull'attività stessa, puoi farlo
in sicurezza implementando ActivityAction
:
@RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testEvent() { launchActivity<MyActivity>().use { scenario -> scenario.onActivity { activity -> activity.handleSwipeToRefresh() } } } }