Compose se integra con frameworks de pruebas comunes.
Interoperabilidad con Espresso
En una app híbrida, puedes encontrar componentes de Compose dentro de jerarquías de vistas y vistas dentro de elementos de Compose (a través del elemento AndroidView).
No es necesario realizar pasos especiales para coincidir con alguno de los tipos. Haz coincidir las vistas con
onView de Espresso y los elementos de Compose con ComposeTestRule.
@Test
fun androidViewInteropTest() {
// Check the initial state of a TextView that depends on a Compose state.
Espresso.onView(withText("Hello Views")).check(matches(isDisplayed()))
// Click on the Compose button that changes the state.
composeTestRule.onNodeWithText("Click here").performClick()
// Check the new value.
Espresso.onView(withText("Hello Compose")).check(matches(isDisplayed()))
}
Agrega semántica con alcance de vista para las pruebas de interoperabilidad de Compose
Limita las búsquedas de Compose a vistas específicas
Cuando migras IU complejas a Compose, es posible que encuentres elementos de Compose idénticos anidados dentro de varias vistas tradicionales de Android, como dentro de un RecyclerView o un ViewPager. En estas situaciones, una búsqueda estándar de Compose, como onNodeWithText("Save"), podría fallar con un error de "Se encontraron varios nodos".
En lugar de modificar tu código de producción para insertar etiquetas de prueba dinámicas que distingan estos elementos, puedes definir el alcance de tu prueba de Compose directamente en una vista de Android específica.
Usa la API de onRootWithViewInteraction en tu regla de prueba. Esta función acepta
un ViewInteraction de Espresso, lo que te permite aprovechar Espresso para aislar una
vista de contenedor específica y realizar interacciones de Compose exclusivamente dentro
de esa jerarquía con alcance.
Cómo interactuar con un elemento de una lista
Si necesitas interactuar con un elemento de Compose dentro de una fila específica de RecyclerView, usa Espresso para ubicar la fila y, luego, limita la interacción de Compose a ella.
Esto ignora los elementos de Compose idénticos en todas las demás filas.
@Test fun testComposeButtonInsideRecyclerViewItem() = runComposeUiTest { // Scroll to the desired position using Espresso Espresso.onView(withId(recyclerViewId)) .perform(RecyclerViewActions.scrollToPosition<MyViewHolder>(3)) // Define an Espresso ViewInteraction that uniquely identifies the row val rowView = Espresso.onView( allOf( withId(rootViewId), hasDescendant(withText("Item #3")) ) ) // Scope the Compose search strictly to that specific row View onRootWithViewInteraction(rowView) .onNode(hasText("Like")) .performClick() }
Cómo resolver la ambigüedad en ViewPagers
Cuando hay varios fragmentos con diseños de Compose idénticos en la memoria simultáneamente, puedes definir el alcance de la búsqueda al ID de la vista raíz del fragmento específico para evitar la ambigüedad de las coincidencias.
@Test fun testComposeButtonInsideViewPagerItem() = runComposeUiTest { // Swipe to the desired page using Espresso Espresso.onView(withId(viewPagerViewId)).perform(swipeLeft()) // Identify the specific container view using Espresso val fragmentB = Espresso.onView(withId(fragmentRootViewId)) // The generic text "Save" is now unique within this view scope onRootWithViewInteraction(fragmentB) .onNode(hasText("Save")) .assertIsDisplayed() }
Interoperabilidad con UiAutomator
De forma predeterminada, solo se puede acceder a los elementos componibles desde UiAutomator a través de sus descriptores convenientes (texto mostrado, descripción del contenido, etcétera). Si quieres
acceder a cualquier elemento componible que use Modifier.testTag, debes habilitar
la propiedad semántica testTagsAsResourceId para el subárbol del elemento componible
en particular. Habilitar este comportamiento es útil para elementos componibles que no tienen ningún otro controlador único, como los que se pueden desplazar (por ejemplo, LazyColumn).
Habilita la propiedad semántica solo una vez que esté alta en la jerarquía de elementos componibles para asegurarte de que se pueda acceder a todos estos elementos anidados con Modifier.testTag desde UiAutomator.
Scaffold(
// Enables for all composables in the hierarchy.
modifier = Modifier.semantics {
testTagsAsResourceId = true
}
){
// Modifier.testTag is accessible from UiAutomator for composables nested here.
LazyColumn(
modifier = Modifier.testTag("myLazyColumn")
){
// Content
}
}
Se puede acceder a cualquier elemento componible con Modifier.testTag(tag) mediante el uso de By.res(resourceName) con el mismo tag que resourceName.
val device = UiDevice.getInstance(getInstrumentation())
val lazyColumn: UiObject2 = device.findObject(By.res("myLazyColumn"))
// Some interaction with the lazyColumn.
Recursos adicionales
- Cómo probar apps en Android: Es la página de destino principal de pruebas de Android, que proporciona una vista más amplia de los aspectos básicos y las técnicas de prueba.
- Aspectos básicos de las pruebas: Obtén más información sobre los conceptos básicos detrás de las pruebas de una app para Android.
- Pruebas locales: Puedes ejecutar algunas pruebas de forma local, en tu propia estación de trabajo.
- Pruebas instrumentadas: También se recomienda ejecutar pruebas instrumentadas. Es decir, pruebas que se ejecutan directamente integrado en el dispositivo.
- Integración continua: La integración continua te permite integrar tus pruebas en la canalización de implementación.
- Prueba diferentes tamaños de pantalla: Con tantos dispositivos disponibles para los usuarios, debes realizar pruebas para diferentes tamaños de pantalla.
- Espresso: Si bien está pensado para las IU basadas en objetos View, el conocimiento de Espresso puede ser útil para algunos aspectos de las pruebas de Compose.