Espresso-Intents

Espresso-Intents es una extensión de Espresso que permite la validación y stubs de intents enviados por el la aplicación que se está probando. Es como Mockito, sino para Android Intents.

Si tu app delega la funcionalidad a otras apps o a la plataforma, puedes usar Espresso-Intents para que se enfoque en la lógica de tu app y asumamos que otras apps o la plataforma funcionará correctamente. Con Espresso-Intents, puedes hacer coincidir y validar tus intents salientes, o incluso proporcionar respuestas de stub en lugar respuestas de intent reales.

Cómo incluir Espresso-Intents en tu proyecto

En el archivo app/build.gradle de tu app, agrega la siguiente línea dependencies

Groovy

androidTestImplementation 'androidx.test.espresso:espresso-intents:3.6.1'

Kotlin

androidTestImplementation('androidx.test.espresso:espresso-intents:3.6.1')

Espresso-Intents solo es compatible con Espresso 2.1+ y con la versión 0.3+ de Bibliotecas de prueba de Android, así que asegúrate de actualizar también esas líneas:

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')

Cómo escribir reglas de prueba

Antes de escribir una prueba de Espresso-Intents, configura una IntentsTestRule. Este es un de la clase ActivityTestRule y facilita su uso APIs de Espresso-Intents en pruebas funcionales de la IU. Se inicializa un IntentsTestRule Espresso-Intents antes de cada prueba anotada con @Test y versiones 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 ofrece la capacidad de interceptar intents salientes en función de determinados criterios de coincidencia, que se definen con los comparadores de Hamcrest. Hamcrest te permite hacer lo siguiente:

  • Usar un comparador de intents existente: Es la opción más fácil, que casi siempre. que prefieras.
  • Implementar tu propio buscador de coincidencias de intent: es la opción más flexible. Más detalles están disponibles en la sección titulada "Cómo escribir comparadores personalizados" en el Instructivo de Hamcrest.

Espresso-Intents ofrece la intended() y intending() para validar intents stubbing, respectivamente. Ambos toman un objeto Matcher<Intent> de Hamcrest como un argumento.

El siguiente fragmento de código muestra la validación de intents que usan intents existentes comparadores que coinciden con 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 intentan iniciar actividades desde el la aplicación que se está probando. Usar el método intended(), que es similar a Mockito.verify(), puedes declarar que se vio un intent determinado. Sin embargo, Espresso-Intents no elimina las respuestas a los intents, a menos que configures explícitamente para hacerlo.

El siguiente fragmento de código es un ejemplo de prueba que valida, pero no como stub respuestas a un intent saliente que inicia un "teléfono" externo actividad:

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 proporcionan una respuesta de stub para las actividades que se inician con startActivityForResult() Esta opción es particularmente útil para actividades externas porque no se puede manipular la interfaz de usuario de una actividad externa ni controlar el objeto ActivityResult que se muestra a la actividad que se está probando.

En los siguientes fragmentos de código, se implementa un ejemplo activityResult_DisplaysContactsPhoneNumber(), que verifica que, cuando un elemento el usuario inicia un "contacto" actividad en la app que estás probando, el teléfono de contacto se muestra el siguiente número:

  1. Compila el resultado que se mostrará cuando se inicie una actividad en particular. El la prueba de ejemplo intercepta todos los intents enviados a "contacts" y apaga su respuestas con un ActivityResult válido, mediante el código de resultado RESULT_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);
    
  2. Indica a Espresso que proporcione el objeto de resultado de stub en respuesta a todos los invocaciones de los "contactos" intent:

    Kotlin

    intending(toPackage("com.android.contacts")).respondWith(result)
    

    Java

    intending(toPackage("com.android.contacts")).respondWith(result);
    
  3. Verifica que la acción utilizada para iniciar la actividad produzca el resultado esperado. de stub. En este caso, la prueba de ejemplo comprueba que el número de teléfono Se muestra "123-345-6789" y que se muestra cuando la "actividad de contactos" se inicia:

    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.

Ejemplos