Tests de UI en Android con Espresso e Idling Resources

Carlos Daniel
Droid LATAM
Published in
4 min readMay 30, 2020

Esta es una traducción del artículo original publicado en The StartUp.

Espresso es el framework que usamos al escribir tests de UI en Android. En términos generales su uso es simple, sin embargo, al escribir test de UI cuando algún proceso de sincronización (por ejemplo consultar datos de un datasource remoto) es llevado a cabo dentro de una app, puede ser tedioso ya que Espresso requiere saber cuándo la sincronización termina (la app entra en modo iddle). Aquí es cuando el trabajar con Idling Resources (IR) entra como protagonistas de la historia.

Imaginemos que le haremos tests de UI a una pantalla que tiene una lista que es poblada con datos desde un endpoint API, por tanto debemos esperar a que el API responda con la data.

La pantalla a testear

Este proceso (obtener, cargar y mostrar la data) puede tomar desde algunos mili segundos hasta un par de segundos para realizarse. Espresso no sabe realmente cuándo nuestra app está en estado idle (de espera) porque solamente puede ver 15 ms en el futuro, entonces si el response toma más de este tiempo, el test fallará.

Así, el framework provee una clase contenedora en la cual podemos “ubicar” los IR, llamada IdlingRegistry, que intriduce un mínimo de overhead a la app y que el equipo de desarrollo de Android recomienda usar:

La idea es la de ejecutar solamente el registro y des-registro de las operaciones de nuestros tests además de la lógica propia de los recursos inactivos (IR) dentro del codebase de producción de nuestra app, queriendo decir que debemos crear nuestro “marcador” de recurso inactivo (IR) dentro del codebase productivo, así, antes que la app llame los endpoints del api remoto seteamos el marcador que le dice a Espresso que el proceso está comenzando y justo cuando obtenemos la respuesta del api, se lo dejamos saber igualmente, así el test que estaba “suspendido” esperando respuesta puede continuar cuando la data ya se obtuvo.

El Paso a Paso

Lo primero, es registrar y des-registrar los recursos inactivos (IR) dentro de los métodos @Before y @After respectivamente:

Como segundo paso, debemos crear el objeto EspressoIdlingResource, que para este caso es del tipo CountingIdlingResource; ya viene dentro del framework y nos permite hace run incremento en nuestro marcador cada vez que comenzamos una tarea (llamado al api endpoint) y un decremento cuando esta termine (el api response). De esa manera podemos controlar mas de una tarea que se inicie concurrentemente. Recordemos que este objeto debe estar dentro del codebase de producción, no dentro del paquete de androidTest:

Finalmente, llamamos los métodos increment() y decrement() dentro del código de producción con las lógicas que vamos a testear (llamados a endpoints):

… y esto es todo, ahora tenemos la posibilidad de testear nuestras pantallas que requieren de procesos largos con Espresso y usando IR.

Recursos Inactivos (IR) en el Codebase de Producción?

Para finalizar, te podrías estar preguntando algo como: debería usar IR en el codebase de producción? Y para responder a esto, remarcaría lo dicho por José Alcérreca del equipo de Android:

Por un lado, son fáciles de usar y hacen el código más testeable. Por otro, estás agregando código a una app que probablemente sea usada por millones de usuarios y que no está haciendo realmente nada propio de ella.
Si te vas por esta ruta, deberías limitar el efecto negativo en producción, por ejemplo, si usas CountingIdlingResource para un objeto, crea diferentes versiones de este objeto, tanto para debug como para release (o para diferentes flavors). La versión de release no debería hacer nada:

Esta lógica de UI Tests con Idling Resources aplicado a un proyecto lo encuentras en esta rama de un proyecto que ya había compartido previamente:

Puedes también revisar este codelab y este artículo de Android Developers con algunos ejemplos prácticos y más información acerca de Espresso.

--

--

Carlos Daniel
Droid LATAM

Android & Flutter Developer. GDE for Android & Mobile Engineer.