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 unCountingIdlingResource
a para mantener el recuento de tareas activas. IdlingScheduledThreadPoolExecutor
- Una implementación personalizada de
ScheduledThreadPoolExecutor
Proporciona la misma la funcionalidad y las capacidadesIdlingThreadPoolExecutor
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 implementacionesisIdleNow()
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.
- Si registras un recurso inactivo en un método anotado con
- 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.
Enfoque recomendado
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, la 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
- IdlingResourceSample: Sincronización con trabajos en segundo plano.