Espresso-Intents es una extensión de Espresso que permite la validación y la implementación de stubs para los intents enviados por la aplicación en modo de prueba. Es similar a Mockito, pero para los intents de Android.
Si la app delega la funcionalidad a otras apps o a la plataforma, puedes usar Espresso-Intents para concentrarte en la lógica de tu app y dar por sentado que otras apps o la plataforma funcionarán correctamente. Con Espresso-Intents, puede igualar y validar los intents salientes o incluso proporcionar respuestas de resguardo en lugar de respuestas reales a intents.
Cómo incluir Espresso-Intents en tu proyecto
En el archivo app/build.gradle
de tu app, agrega la siguiente línea dentro de dependencies
:
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
Espresso-Intents solo es compatible con Espresso 2.1 y versiones posteriores, y con la versión 0.3 y posteriores de las bibliotecas de prueba de Android, de modo que asegúrate de actualizar también esas líneas:
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
Cómo escribir reglas de prueba
Antes de escribir una prueba de Espresso-Intents, configura una IntentsTestRule
. Esta es una extensión de la clase ActivityTestRule
que facilita el uso de las API de Espresso-Intents en pruebas funcionales de la IU. Una IntentsTestRule
inicializa Espresso-Intents antes de cada prueba anotada con @Test
y hace una actualización de Espresso-Intents después de cada ejecución de prueba.
El siguiente fragmento de código es un ejemplo de una IntentsTestRule
:
Kotlin
@get:Rule val intentsTestRule = IntentsTestRule(MyActivity::class.java)
Java
@Rule public IntentsTestRule<MyActivity> intentsTestRule = new IntentsTestRule<>(MyActivity.class);
Coincidencia
Espresso-Intents permite interceptar intents salientes en función de ciertos criterios de coincidencia, que se definen mediante los comparadores de Hamcrest. Hamcrest te permite:
- Usar un buscador de coincidencias de intent existente: es la opción más fácil y la más recomendada.
- Implementar tu propio buscador de coincidencias de intent: es la opción más flexible. Para obtener más información, consulta la sección "Cómo escribir buscadores de coincidencias personalizados" del instructivo de Hamcrest.
Espresso-Intents ofrece los métodos intended()
y intending()
para la validación y la implementación de stubs para los intents, respectivamente. Ambos toman un objeto Matcher<Intent>
de Hamcrest como argumento.
En el siguiente fragmento de código, se muestra la validación de intents que utilizan buscadores de coincidencias de intents existentes para un intent saliente que inicia un navegador:
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");
Cómo validar intents
Espresso-Intents registra todos los intents que tratan de iniciar actividades desde la aplicación sometida a prueba. Con el método intended()
, que es similar a Mockito.verify()
, puedes declarar que se vio un intent determinado. Sin embargo, Espresso-Intents no crea stubs de respuestas a los intents, a menos que lo configures explícitamente para hacerlo.
El siguiente fragmento de código es una prueba de ejemplo que valida, pero no elimina las respuestas a un intent saliente que inicia una actividad externa de "teléfono":
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")); }
Cómo implementar stubs
Con el método intending()
, que es similar a Mockito.when()
, puedes proporcionar una respuesta de stub para las actividades que se inician con startActivityForResult()
. Esto es particularmente útil para actividades externas, porque no puedes manipular la interfaz de usuario de una actividad externa ni controlar el ActivityResult
que se muestra para la actividad que se está probando.
En los siguientes fragmentos de código, se implementa una prueba de activityResult_DisplaysContactsPhoneNumber()
de ejemplo, que verifica que cuando un usuario inicia una actividad de "contacto" en la app que se está probando, se muestra el número de teléfono de contacto:
Compila el resultado que se mostrará cuando se inicie una actividad en particular. La prueba de ejemplo intercepta todos los Intents enviados a "contactos" y envía sus respuestas de stub con un
ActivityResult
válido, a través del código de resultadoRESULT_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);
Indica a Espresso que proporcione el objeto de resultado de stub en respuesta a todas las invocaciones con el intent "contacts":
Kotlin
intending(toPackage("com.android.contacts")).respondWith(result)
Java
intending(toPackage("com.android.contacts")).respondWith(result);
Verifica que la acción utilizada para iniciar la actividad produzca el resultado de stub esperado. En este caso, la prueba de ejemplo verifica que se muestra el número de teléfono "123-345-6789" cuando se inicia la "actividad de contactos":
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)));
Esta es la prueba completa de activityResult_DisplaysContactsPhoneNumber()
:
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))); }
Recursos adicionales
Para obtener más información sobre el uso de Espresso-Intents en las pruebas de Android, consulta los siguientes recursos.
Muestras
- IntentsBasicSample: uso básico de
intended()
yintending()
- IntentsAdvancedSample: simula a un usuario que obtiene un mapa de bits con la cámara