Fundamentos de UI Testing
Clase 12 de 16 • Curso de Android Testing
Resumen
La prueba de interfaces de usuario en aplicaciones Android es un componente esencial para garantizar experiencias de usuario fluidas y libres de errores. Cuando trabajamos con Jetpack Compose, el moderno toolkit de UI para Android, tenemos a nuestra disposición herramientas específicas que nos permiten verificar el comportamiento visual y funcional de nuestros componentes. Estas pruebas nos ayudan a detectar problemas temprano en el ciclo de desarrollo, ahorrando tiempo y recursos valiosos.
¿Cómo implementar pruebas de UI en Jetpack Compose?
Jetpack Compose ofrece un framework de testing robusto que nos permite verificar que nuestros componentes visuales se comporten como esperamos. A diferencia de las pruebas unitarias tradicionales, las pruebas de UI en Compose requieren un enfoque diferente, ya que necesitamos montar componentes visuales en un entorno controlado.
Configuración del entorno de pruebas
Para comenzar a testear interfaces en Compose, necesitamos configurar correctamente nuestro entorno de pruebas:
-
Ubicación de las pruebas: Las pruebas de UI deben colocarse en la carpeta
androidTest
, no en la carpeta de pruebas unitarias, ya que interactúan con componentes del framework Android. -
ComposeTestRule: Esta es la regla principal que necesitamos para montar nuestros composables en un entorno de prueba.
@get:Rule
val composeRule = createComposeRule()
Esta regla nos proporciona una actividad aislada específicamente para pruebas y nos da acceso al método setContent()
, que nos permite cargar nuestros composables para probarlos.
Semantic testing con Finders y Matchers
Una de las características más potentes del framework de testing de Compose es el Semantic testing, que nos permite:
- Encontrar elementos en la jerarquía de composables usando Finders
- Verificar propiedades de estos elementos usando Matchers
Los principales métodos para encontrar elementos son:
onNodeWithText()
: Encuentra un nodo que contiene un texto específicoonNodeWithContentDescription()
: Encuentra un nodo con una descripción de contenido específica (importante para accesibilidad)
composeRule.onNodeWithText("Welcome test user!").assertIsDisplayed()
composeRule.onNodeWithContentDescription("loading profile").assertIsDisplayed()
¿Cómo probar diferentes estados de UI?
Una de las ventajas de la arquitectura de Compose es que la UI es una función del estado. Esto significa que podemos probar fácilmente diferentes estados de nuestra interfaz proporcionando diferentes estados como entrada.
Probando el estado de carga
Para probar cómo se ve nuestra UI cuando está cargando datos:
@Test
fun profileScreen_whenLoading_showsLoadingIndicator() {
composeRule.setContent {
MaterialTheme {
ProfileScreen(
state = ProfileState(
profile = null,
isLoading = true,
errorMessage = null
),
onPlaceClick = {}
)
}
}
composeRule.onNodeWithContentDescription("loading profile").assertIsDisplayed()
}
Probando el estado con datos cargados
Para verificar que nuestra UI muestra correctamente los datos cuando están disponibles:
@Test
fun profileScreen_whenProfileLoaded_showsUserAndPlaces() {
val state = ProfileState(
profile = Profile(
username = "test user",
places = listOf(
Place(id = "1", name = "place 1", latitude = 1.1, longitude = 1.1),
Place(id = "2", name = "place 2", latitude = 2.2, longitude = 2.2)
)
),
isLoading = false,
errorMessage = null
)
composeRule.setContent {
MaterialTheme {
ProfileScreen(
state = state,
onPlaceClick = {}
)
}
}
composeRule.onNodeWithText("Welcome test user!").assertIsDisplayed()
composeRule.onNodeWithText("place 1").assertIsDisplayed()
composeRule.onNodeWithText("1.1").assertIsDisplayed()
}
Probando el estado de error
Es igualmente importante verificar que nuestra UI maneje correctamente los estados de error:
@Test
fun profileScreen_whenError_showsErrorMessage() {
val errorMessage = "Failed to load profile"
composeRule.setContent {
MaterialTheme {
ProfileScreen(
state = ProfileState(
profile = null,
isLoading = false,
errorMessage = errorMessage
),
onPlaceClick = {}
)
}
}
composeRule.onNodeWithText(errorMessage).assertIsDisplayed()
}
Buenas prácticas para pruebas de UI en Compose
Para mantener nuestras pruebas de UI efectivas y mantenibles, es recomendable seguir estas prácticas:
-
Usar descripciones de contenido: Agregar
contentDescription
a los elementos importantes no solo mejora la accesibilidad, sino que también facilita encontrar estos elementos en las pruebas. -
Pruebas específicas y enfocadas: Cada prueba debe verificar un escenario específico (carga, datos, error) en lugar de intentar probar todo en una sola prueba.
-
Evitar esperas fijas: Aunque podemos usar
Thread.sleep()
para visualizar temporalmente la UI durante las pruebas, en pruebas reales es mejor usar métodos comowaitForIdle()
owaitUntil()
para condiciones específicas. -
Nombrar pruebas descriptivamente: Los nombres de las pruebas deben describir claramente el escenario que están probando y el resultado esperado.
Las pruebas de UI en Jetpack Compose nos permiten verificar que nuestros componentes visuales funcionan correctamente en diferentes escenarios, proporcionando una capa adicional de confianza en nuestro código. Al combinar estas pruebas con pruebas unitarias tradicionales, podemos construir aplicaciones más robustas y con menos errores.
¿Has implementado pruebas de UI en tus proyectos con Compose? ¿Qué desafíos has encontrado? Comparte tu experiencia en los comentarios.