Espresso-Intents è un'estensione di Espresso che consente la convalida e la creazione di stub degli intent inviati dall'applicazione in fase di test. È simile a Mockito, ma per gli intent di Android.
Se la tua app delega funzionalità ad altre app o alla piattaforma, puoi utilizzare Espresso-Intents per concentrarti sulla logica della tua app, presupponendo che altre app o la piattaforma funzionino correttamente. Con Espresso-Intents, puoi abbinare e convalidare gli intent in uscita o persino fornire risposte stub al posto delle risposte intent effettive.
Includere Espresso-Intents nel progetto
Nel file app/build.gradle
dell'app, aggiungi la seguente riga all'interno di
dependencies
:
Groovy
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.6.1'
Kotlin
androidTestImplementation('androidx.test.espresso:espresso-intents:3.6.1')
Espresso-Intents è compatibile solo con Espresso 2.1+ e con la versione 0.3+ delle librerie di test Android, quindi assicurati di aggiornare anche queste righe:
Groovy
androidTestImplementation 'androidx.test:runner:1.6.1' androidTestImplementation 'androidx.test:rules:1.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
Kotlin
androidTestImplementation('androidx.test:runner:1.6.1') androidTestImplementation('androidx.test:rules:1.6.1') androidTestImplementation('androidx.test.espresso:espresso-core:3.6.1')
Scrivere le regole di test
Prima di scrivere un test Espresso-Intents, configura un IntentsTestRule
. Si tratta di un'estensione della classe ActivityTestRule
e semplifica l'utilizzo delle API Espresso-Intents nei test UI funzionali. Un IntentsTestRule
inizializza
Espresso-Intents prima di ogni test annotato con @Test
e rilascia
Espresso-Intents dopo ogni esecuzione del test.
Il seguente snippet di codice è un esempio di IntentsTestRule
:
Kotlin
@get:Rule val intentsTestRule = IntentsTestRule(MyActivity::class.java)
Java
@Rule public IntentsTestRule<MyActivity> intentsTestRule = new IntentsTestRule<>(MyActivity.class);
Corrispondenza
Espresso-Intents offre la possibilità di intercettare gli intent in uscita in base a determinati criteri di corrispondenza, definiti utilizzando Hamcrest Matchers. Hamcrest ti consente di:
- Utilizzare un matcher di intent esistente:l'opzione più semplice, che dovrebbe essere preferita quasi sempre.
- Implementa il tuo matcher di intent: l'opzione più flessibile. Per ulteriori dettagli, consulta la sezione "Writing custom matchers" (Scrittura di matcher personalizzati) del tutorial su Hamcrest.
Espresso-Intents offre i metodi intended()
e intending()
per la convalida e la creazione di stub degli intent, rispettivamente. Entrambi accettano un oggetto Hamcrest Matcher<Intent>
come
argomento.
Il seguente snippet di codice mostra la convalida dell'intent che utilizza i matcher di intent esistenti che corrispondono a un intent in uscita che avvia un browser:
Kotlin
assertThat(intent).hasAction(Intent.ACTION_VIEW) assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE) assertThat(intent).hasData(Uri.parse("www.google.com")) assertThat(intent).extras().containsKey("key1") assertThat(intent).extras().string("key1").isEqualTo("value1") assertThat(intent).extras().containsKey("key2") assertThat(intent).extras().string("key2").isEqualTo("value2")
Java
assertThat(intent).hasAction(Intent.ACTION_VIEW); assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE); assertThat(intent).hasData(Uri.parse("www.google.com")); assertThat(intent).extras().containsKey("key1"); assertThat(intent).extras().string("key1").isEqualTo("value1"); assertThat(intent).extras().containsKey("key2"); assertThat(intent).extras().string("key2").isEqualTo("value2");
Convalidare gli intent
Espresso-Intents registra tutti gli intent che tentano di avviare attività dall'applicazione in fase di test. Utilizzando il metodo intended()
, simile a Mockito.verify()
, puoi affermare che un determinato intent è stato visualizzato. Tuttavia,
Espresso-Intents non esegue lo stub delle risposte agli intent, a meno che tu non lo configuri esplicitamente
per farlo.
Il seguente snippet di codice è un test di esempio che convalida, ma non simula le risposte a un intent in uscita che avvia un'attività "telefono" esterna:
Kotlin
@Test fun validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)) // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")) }
Java
@Test public void validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)); // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")); }
Stubbing
Utilizzando il metodo intending()
, simile a Mockito.when()
, puoi
fornire una risposta stub per le attività avviate con
startActivityForResult()
. Ciò è particolarmente utile per le attività esterne
perché non puoi manipolare l'interfaccia utente di un'attività esterna né
controllare ActivityResult
restituito all'attività in fase di test.
I seguenti snippet di codice implementano un test activityResult_DisplaysContactsPhoneNumber()
di esempio, che verifica che quando un utente avvia un'attività "contatto" nell'app in fase di test, venga visualizzato il numero di telefono del contatto:
Crea il risultato da restituire quando viene avviata una determinata attività. L'esempio di test intercetta tutti gli intent inviati a "contacts" e simula le relative risposte con un
ActivityResult
valido, utilizzando il codice risultatoRESULT_OK
Kotlin
val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)
Java
Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData);
Chiedi a Espresso di fornire l'oggetto risultato stub in risposta a tutte le invocazioni dell'intent "contacts":
Kotlin
intending(toPackage("com.android.contacts")).respondWith(result)
Java
intending(toPackage("com.android.contacts")).respondWith(result);
Verifica che l'intent utilizzato per avviare l'attività produca il risultato stub previsto. In questo caso, il test di esempio verifica che il numero di telefono "123-345-6789" venga restituito e visualizzato all'avvio dell'attività "Contatti":
Kotlin
onView(withId(R.id.pickButton)).perform(click()) onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)))
Java
onView(withId(R.id.pickButton)).perform(click()); onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)));
Ecco il test activityResult_DisplaysContactsPhoneNumber()
completo:
Kotlin
@Test fun activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData) // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result) // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()) // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))) }
Java
@Test public void activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData); // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result); // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()); // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))); }
Risorse aggiuntive
Per saperne di più sull'utilizzo di Espresso-Intents nei test Android, consulta le seguenti risorse.
Campioni
- IntentsBasicSample:
Utilizzo di base di
intended()
eintending()
. - IntentsAdvancedSample: Simula un utente che recupera una bitmap utilizzando la fotocamera.