Como mobile developers, pasamos la mayor parte de tiempo creando nuevas pantallas o cambiando pantallas que ya existen y necesitamos saber que el código funciona. Es por eso que en nuestro proceso de desarrollo debemos utilizar herramientas para verificar que nuestra aplicación sigue funcionando como esperamos y que nuestro desarrollo cumple con la calidad del producto deseada según la historia de usuario. En este artículos trataremos el Espresso UI Test.

Asegurarnos que:

  • Mostramos la información correcta al usuario cuando la UI está cargada
  • Mostrar el mensaje o pantalla deseada dada una acción del usuario

 

Para cumplir con este objetivo existen varios tipos de test de ui:

 

  • Classic ui testing -> se enfoca en vistas y sus interacciones.
  • Snapshot testing -> garantiza el diseño perfecto, dejando a un lado las interacciones.

 

 

¿ Que es Espresso UI Test? ¿Como funciona?

 

Espresso es un framework creado por Google para Android que nos permite escribir test sobre la interfaz de usuario.

Dispone de una simple API, fácil de adaptar a nuestras necesidades y elimina la complejidad de la gestión de distintos hilos de ejecución.

Espresso UI Test funciona basicamente en tres bloques:

  • ViewMatchers – permite encontrar un elemento en la vista
  • ViewActions – permite ejecutar acciones sobre los elementos
  • ViewAssertions – valida un estado de la vista

Trabajando con espresso es recomendable tener esta hoja cerca.

 

Configuración

Para qué espresso funcione en nuestro proyecto necesitamos agregar la dependencias en nuestro archivo ‘app/build.gradle’ y un dispositivo físico o virtual.


dependencies {
 implementation fileTree(dir: 'libs', include: ['*.jar'])
 testImplementation 'junit:junit:4.12'

   // Android runner and rules support
 androidTestImplementation 'com.android.support.test:runner:1.0.2'
 androidTestImplementation 'com.android.support.test:rules:1.0.2'

   // Espresso
 androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Es recomendable apagar la animaciones de nuestro dispositivo android que utilizaremos para los test en las opciones de desarrollador. Una forma fácil de hacerlo es ejecutando estos comandos desde tu terminal:

 
adb shell settings put global window_animation_scale 0.0 
adb shell settings put global transition_animation_scale 0.0 
adb shell settings put global animator_duration_scale 0.0

 

Implementación

Como pequeño ejercicio práctico hemos creado una vista con dos textviews y un botón donde queremos evaluar que cuando presionemos el botón se esconda un textview y se muestre otro.

espresso android

 

Podemos crear nuestro test ui de forma automática mediante la herramienta récord de espresso o manualmente.

 

  • Record Espresso

Para ello debemos ir en la barra de opciones de android studio a Run -> Record Espresso Test

Nos lanzará una pantalla donde podemos ir haciendo aserciones

espresso

Y al terminar nos generará el código del test:

 
@LargeTest
@RunWith(AndroidJUnit4.class)
public class RecordedTextViewToggleVisibilityTest {

  @Rule
  public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(MainActivity.class);

  @Test
  public void textViewToggleVisibilityTest() {
    ViewInteraction textView = onView(
        allOf(withId(R.id.tv_hello), withText("Hello buddy!"),
            childAtPosition(
                childAtPosition(
                    withId(android.R.id.content),
                    0),
                0),
            isDisplayed()));
    textView.check(matches(withText("Hello buddy!")));

    ViewInteraction appCompatButton = onView(
        allOf(withId(R.id.button), withText("click me"),
            childAtPosition(
                childAtPosition(
                    withId(android.R.id.content),
                    0),
                2),
            isDisplayed()));
    appCompatButton.perform(click());

    ViewInteraction textView2 = onView(
        allOf(withId(R.id.tv_see_you), withText("See you"),
            childAtPosition(
                childAtPosition(
                    withId(android.R.id.content),
                    0),
                1),
            isDisplayed()));
    textView2.check(matches(isDisplayed()));
  }

  private static Matcher childAtPosition(
      final Matcher parentMatcher, final int position) {

    return new TypeSafeMatcher() {
      @Override
      public void describeTo(Description description) {
        description.appendText("Child at position " + position + " in parent ");
        parentMatcher.describeTo(description);
      }

      @Override
      public boolean matchesSafely(View view) {
        ViewParent parent = view.getParent();
        return parent instanceof ViewGroup && parentMatcher.matches(parent)
            && view.equals(((ViewGroup) parent).getChildAt(position));
      }
    };
  }
}

 

  • Forma manual
 
@LargeTest
@RunWith(AndroidJUnit4.class)
public class ManualTextViewToggleVisibilityTest {

  @Rule
  public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(MainActivity.class);

  @Test
  public void textViewToggleVisibilityTest() {


    // here we are going to look in the view tree
    // we use allOff from hamcrest library to combine matchers
    ViewInteraction tvHello = onView(allOf(withId(R.id.tv_hello),withText(R.String.hello_buddy)));

    ViewInteraction tvSeeYou = onView(allOf(withId(R.id.tv_see_you),withText(R.String.see_you)));

    // assert that textView with text 'Hello buddy!' is display
    tvHello.check(matches(isDisplayed()));


    // assert that textView with text 'See you' has visibility gone
tvSeeYou.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)));

    // find button with given id and click
    onView(withId(R.id.button)).perform(click());

    // assert see you is visible and hello buddy is not.        tvHello.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)));
    tvSeeYou.check(matches(isDisplayed()));
  }
}

 

Podemos comprobar que Espresso de forma automática nos ha generado mas codigo, el cual se puede romper fácilmente y necesitará un mayor mantenimiento. Por ejemplo a utilizado el string literal para encontrar la vista y en caso de cambiar el idioma al dispositivo el test fallaría, sin embargo de forma manual podemos utilizar el id del string resource y agregar tantos matchers como necesitemos.

Esta guía de referencia hamcrest te puede ser útil a la hora de trabajar con matchers.

 

Conclusión

Como humanos somos propensos a cometer errores y esto implica que nuestro software sea vulnerable a bugs y defectos. Espresso nos ayuda a detectar los errores que se puedan haber cometido en el desarrollo asegurando la confiabilidad del Cliente y su satisfacción con la aplicación.

Si aún no has agregado Espresso a tus herramientas de desarrollo piensa en las personas que tendrán que probar la aplicación manualmente.

 

Suscríbete a nuestro newsletter para estar al día de Espresso UI Test !

 

Si este artículo sobre Espresso UI Test te gustó, te puede interesar:

 

Tendencias en aplicaciónes móviles

Patrón MVP en iOS

Debugging con Charles Proxy en Android emulator

Por qué Kotlin?   

Integración Continua en iOS usando Fastlane y Jenkins  

Meetups de arquitectura de software  

MVPP en Android