Recursos inactivos de Espresso

Un recurso inactivo representa una operación asíncrona cuyos resultados afectan. las operaciones posteriores en una prueba de IU. Mediante el registro de recursos inactivos con Espresso, puedes validar estas operaciones asíncronas de forma más confiable cuando probar tu app.

Cómo identificar si se necesitan recursos inactivos

Espresso ofrece un sofisticado conjunto de capacidades de sincronización. Esta característica del framework, sin embargo, se aplica solo a las operaciones que publiquen mensajes en el MessageQueue, como una subclase de View que dibuja el contenido en la pantalla.

Debido a que Espresso no conoce otras operaciones asíncronas, como con aquellos que se ejecutan en un subproceso en segundo plano, Espresso no puede proporcionar su sincronización garantías en esas situaciones. Para que Espresso conozca la infraestructura operaciones de larga duración, debes registrar cada una como un recurso inactivo.

Si no usas recursos inactivos al probar los resultados trabajo asíncrono, puede que tengas que usar uno de los seguir soluciones malas para mejorar la capacidad confiabilidad:

  • Agregar llamadas a Thread.sleep(). Cuando agregar retrasos artificiales a tus pruebas, ya que el paquete de pruebas tarda más terminen de ejecutarse y es posible que a veces las pruebas fallen cuando se ejecuten dispositivos más lentos. Además, estas demoras no se adaptan bien, ya que tu app podría deberán realizar más trabajo asíncrono que demanda más tiempo en una versión futura.
  • Implementar wrappers de reintento, que usan un bucle para verificar repetidamente si tu app continúa realizando trabajo asíncrono hasta que se agota el tiempo de espera. Incluso si especificas un recuento máximo de reintentos en tus pruebas, cada reejecución consume los recursos del sistema, en especial la CPU.
  • Usar instancias de CountDownLatch, que permiten que uno o más subprocesos esperen hasta que se realice una determinada cantidad de operaciones que se ejecuten en otro subproceso. Estos objetos requieren que especifiques una duración del tiempo de espera; De lo contrario, tu app podría bloquearse indefinidamente. Los cierres agregan complejidad innecesaria a tu código, lo que dificulta el mantenimiento.

Espresso permite quitar estas soluciones poco confiables de sus pruebas y en su lugar, registra el trabajo asíncrono de tu app como recursos inactivos.

Casos de uso comunes

Cuando realices operaciones similares a las de los siguientes ejemplos en tus pruebas, considera usar un recurso inactivo:

  • Carga datos desde Internet o una fuente de datos local.
  • Establece conexiones con bases de datos y devoluciones de llamadas.
  • Administrar servicios, ya sea mediante un servicio del sistema o una instancia de IntentService
  • Desarrolla una lógica empresarial compleja, como transformaciones de mapas de bits.

Es muy importante registrar los recursos inactivos cuando estas operaciones actualizarás una IU que luego validarán tus pruebas.

Ejemplo de implementaciones de recursos inactivos

En la siguiente lista, se describen varios ejemplos de implementaciones de recursos inactivos que puedes integrar a tu app:

CountingIdlingResource
Realiza un recuento de tareas activas. Cuando el contador es cero, el valor recurso se considera inactivo. Esta funcionalidad se asemeja mucho a la de un Semaphore En la mayoría de los casos, esta implementación suficientes para administrar el trabajo asíncrono de tu app durante las pruebas.
UriIdlingResource
Similar a CountingIdlingResource, pero el contador debe ser cero por un período específico antes de recurso se considera inactivo. Este período de espera adicional dura en cuenta las solicitudes de red, cuando una app de tu subproceso podría crear un nuevo solicitud inmediatamente después de recibir una respuesta a una solicitud anterior.
IdlingThreadPoolExecutor
Una implementación personalizada de ThreadPoolExecutor que realiza un seguimiento de la cantidad total de tareas en ejecución dentro del subproceso creado piscinas. Esta clase usa un CountingIdlingResource a para mantener el recuento de tareas activas.
IdlingScheduledThreadPoolExecutor
Una implementación personalizada de ScheduledThreadPoolExecutor Proporciona la misma la funcionalidad y las capacidades IdlingThreadPoolExecutor pero también puede hacer un seguimiento de las tareas programadas para el futuro o están programados para ejecutarse periódicamente.

Crea tu propio recurso inactivo

Como usas recursos inactivos en las pruebas de tu app, es posible que debas proporcionar administrar o registrar recursos personalizados. En esos casos, las implementaciones que se mencionan en la sección anterior podrían no ser suficientes. Si ese es el caso, puedes puedes extender una de estas implementaciones de recursos inactivos o crear una propia.

Si implementas tu propia funcionalidad de recursos inactivos, conserva lo siguiente: prácticas recomendadas, especialmente la primera:

Invoca transiciones al estado inactivo fuera de las comprobaciones inactivas.
Una vez que la app esté inactiva, llama onTransitionToIdle() fuera de las implementaciones isIdleNow() De esa manera, Espresso no realiza una segunda comprobación innecesaria para determinar si un determinado el recurso inactivo está inactivo.

En el siguiente fragmento de código, se muestra un ejemplo de esta recomendación:

Kotlin

fun isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

fun backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}

Java

public void isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

public void backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}
Registra los recursos inactivos antes de que los necesites.

Los beneficios de sincronización asociados con los recursos inactivos solo tienen efecto después de la primera invocación de Espresso de la instancia isIdleNow().

En la siguiente lista, se muestran varios ejemplos de esta propiedad:

  • Si registras un recurso inactivo en un método anotado con @Before, el recurso inactivo se aplica en la primera línea de cada prueba.
  • Si registras un recurso inactivo dentro de una prueba, ese recurso se aplica durante la siguiente acción basada en Espresso. Este comportamiento aún incluso si la siguiente acción está en la misma prueba que la instrucción que registra el recurso inactivo.
Cancela el registro de los recursos inactivos una vez que hayas terminado de usarlos.

Para conservar los recursos del sistema, debes cancelar el registro de los recursos inactivos lo antes posible porque ya no los necesitas. Por ejemplo, si registras un recurso inactivo En un método anotado con @Before, es mejor cancelar el registro de este recurso en un método correspondiente anotado con @After.

Usa un registro inactivo para registrar y cancelar el registro de recursos inactivos.

Si usas este contenedor para los recursos inactivos de tu app, puedes registrar y cancelar el registro de los recursos inactivos repetidamente según sea necesario y seguir observando el comportamiento de los usuarios.

Mantén solo el estado simple de la app dentro de los recursos inactivos.

Por ejemplo, los recursos inactivos que implementas y registras no deben contienen referencias a objetos View.

Registra recursos inactivos

Espresso proporciona una clase de contenedor en la que puedes colocar el valor de inactividad de tu app de Google Cloud. Esta clase, llamada IdlingRegistry es un artefacto autónomo que introduce una sobrecarga mínima en tu app. La clase también te permite realizar los siguientes pasos para mejorar el rendimiento capacidad de mantenimiento:

  • Crea una referencia a IdlingRegistry, en lugar de los recursos inactivos que contiene, en las pruebas de tu app.
  • Mantener las diferencias en la colección de recursos inactivos que usas para para cada variante de compilación.
  • Cómo definir recursos inactivos en los servicios de tu app, en lugar de la IU componentes que hacen referencia a esos servicios.

Integra recursos inactivos en tu app

Aunque puedes agregar recursos inactivos a una app de varias maneras diferentes, una en particular mantiene el encapsulamiento de tu app y, al mismo tiempo, permite te permite especificar una operación en particular que representa un recurso inactivo determinado.

Si agregas recursos inactivos a tu app, te recomendamos ubicar la lógica de recursos inactiva en la app y solo realizar el registro y operaciones de cancelación del registro en tus pruebas.

Aunque creas la situación inusual de usar una interfaz de solo prueba en de producción, con este enfoque, puedes unir los recursos inactivos y el código que ya tienes, y mantiene el tamaño del APK de la app y el recuento de métodos.

Enfoques alternativos

Si prefieres no tener una lógica de recursos inactivos en la producción de tu app código, existen otras estrategias de integración viables:

  • Crear variantes de compilación, como las de Gradle producto variantes y usa recursos inactivos solo en la compilación de depuración de tu app.
  • Usa un framework de inserción de dependencias, como Dagger, para inyectar el estado de inactividad de tu app. gráfico de dependencia de recursos en tus pruebas. Si usas Dagger 2, las debe provenir de un subcomponente.
  • Implementa un recurso inactivo en las pruebas de tu app y expone la parte de la implementación de tu app que deben sincronizarse y pruebas.

    Precaución: Aunque esta decisión de diseño parece una referencia independiente a los recursos inactivos, también rompe en todas las apps, excepto en la más simple.

Recursos adicionales

Para obtener más información sobre el uso de Espresso en pruebas de Android, consulta el los siguientes recursos.

Ejemplos