Aspectos básicos de las pruebas de apps para Android

En esta página, se describen los principios fundamentales de las pruebas de apps para Android, incluidas las prácticas recomendadas centrales y sus beneficios.

Beneficios de las pruebas

Probar la app es una parte integral del proceso de desarrollo. Cuando ejecutas pruebas de manera constante, puedes verificar la precisión, el comportamiento funcional y la usabilidad de la app antes de lanzarla públicamente.

Puedes probar tu app manualmente navegando por ella. Es posible que uses diferentes dispositivos y emuladores, cambies el idioma del sistema y trates de generar todos los errores del usuario o recorrer todos los flujos del usuario.

Sin embargo, las pruebas manuales no se adaptan bien a gran escala y es fácil pasar por alto las regresiones en el comportamiento de tu app. La prueba automatizada implica el uso de herramientas que realizan pruebas por ti, lo que es más rápido, más repetible y, en general, te brinda comentarios más prácticos sobre tu app en una etapa más temprana del proceso de desarrollo.

Tipos de pruebas en Android

Las aplicaciones para dispositivos móviles son complejas y deben funcionar bien en muchos entornos. Por lo tanto, existen muchos tipos de pruebas.

Asunto

Por ejemplo, existen diferentes tipos de pruebas según el sujeto:

  • Pruebas funcionales: ¿Mi app hace lo que se supone que debe hacer?
  • Pruebas de rendimiento: ¿Se realizan de forma rápida y eficiente?
  • Pruebas de accesibilidad: ¿Funciona bien con los servicios de accesibilidad?
  • Pruebas de compatibilidad: ¿Funciona bien en todos los dispositivos y niveles de API?

Alcance

Las pruebas también varían según el tamaño o el grado de aislamiento:

  • Las pruebas de unidades o pruebas de nivel inferior solo verifican una porción muy pequeña de la app, como un método o una clase.
  • Las pruebas de extremo a extremo o de nivel superior verifican partes más grandes de la app al mismo tiempo, como una pantalla completa o un flujo del usuario.
  • Las pruebas de nivel intermedio se encuentran en el medio y verifican la integración entre dos o más unidades.
Las pruebas pueden ser pequeñas, medianas o grandes.
Figura 1: Permisos de prueba en una aplicación típica.

Existen muchas formas de clasificar las pruebas. Sin embargo, la distinción más importante para los desarrolladores de apps es dónde se ejecutan las pruebas.

Comparación entre las pruebas instrumentadas y las locales

Puedes ejecutar pruebas en un dispositivo Android o en otra computadora:

  • Las pruebas instrumentadas se ejecutan en un dispositivo Android, ya sea físico o emulado. La app se compila y se instala junto con una app de prueba que inserta comandos y lee el estado. Las pruebas instrumentadas suelen ser pruebas de IU que inician una app y, luego, interactúan con ella.
  • Las pruebas locales se ejecutan en tu máquina de desarrollo o en un servidor, por lo que también se denominan pruebas del host. Por lo general, son pequeñas y rápidas, y aíslan el sujeto de la prueba del resto de la app.
Las pruebas pueden ejecutarse como pruebas instrumentadas en un dispositivo o como pruebas locales en tu máquina de desarrollo.
Figura 2: Diferentes tipos de pruebas según dónde se ejecutan.

No todas las pruebas de unidades son locales, y no todas las pruebas de extremo a extremo se ejecutan en un dispositivo. Por ejemplo:

  • Prueba local grande: Puedes usar un simulador de Android que se ejecute de forma local, como Robolectric.
  • Prueba instrumentada pequeña: Puedes verificar que tu código funcione bien con una función del framework, como una base de datos SQLite. Puedes ejecutar esta prueba en varios dispositivos para verificar la integración con varias versiones de SQLite.

Ejemplos

En los siguientes fragmentos, se muestra cómo interactuar con la IU en una prueba de IU instrumentada que hace clic en un elemento y verifica que se muestre otro elemento.

Espresso

// When the Continue button is clicked
onView(withText("Continue"))
    .perform(click())

// Then the Welcome screen is displayed
onView(withText("Welcome"))
    .check(matches(isDisplayed()))

IU de Compose

// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()

// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()

Este fragmento muestra parte de una prueba de unidades para un ViewModel (prueba local del host):

// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)

// When data is loaded
viewModel.loadData()

// Then it should be exposing data
assertTrue(viewModel.data != null)

Arquitectura verificable

Con una arquitectura de app que se puede probar, el código sigue una estructura que te permite probar fácilmente diferentes partes de forma aislada. Las arquitecturas que se pueden probar tienen otras ventajas, como una mejor legibilidad, capacidad de mantenimiento, escalabilidad y reutilización.

Una arquitectura que no se puede probar produce lo siguiente:

  • Pruebas más grandes, lentas y poco confiables Es posible que las clases que no se pueden probar de forma unitaria deban incluirse en pruebas de integración o de IU más grandes.
  • Menos oportunidades para probar diferentes situaciones Las pruebas más grandes son más lentas, por lo que probar todos los estados posibles de una app podría ser poco realista.

Para obtener más información sobre los lineamientos de arquitectura, consulta la guía de arquitectura de apps.

Enfoques para el desacoplamiento

Si puedes extraer parte de una función, una clase o un módulo del resto, probarlo es más fácil y efectivo. Esta práctica se conoce como desacoplamiento y es el concepto más importante para la arquitectura verificable.

Entre las técnicas de desacoplamiento comunes, se incluyen las siguientes:

  • Divide una app en capas, como Presentación, Dominio y Datos. También puedes dividir una app en módulos, uno por función.
  • Evita agregar lógica a las entidades que tienen grandes dependencias, como las actividades y los fragmentos. Usa estas clases como puntos de entrada al framework y mueve la lógica empresarial y de la IU a otro lugar, como un elemento Composable, un ViewModel o una capa de dominio.
  • Evita las dependencias del framework directas en las clases que contienen lógica empresarial. Por ejemplo, no uses contextos de Android en ViewModels.
  • Facilita el reemplazo de las dependencias. Por ejemplo, usa interfaces en lugar de implementaciones concretas. Usa la inserción de dependencias, incluso si no usas un framework de DI.

Próximos pasos

Ahora que sabes por qué debes realizar pruebas y los dos tipos principales de pruebas, puedes leer Qué probar o aprender sobre las Estrategias de prueba.

Como alternativa, si quieres crear tu primera prueba y aprender mientras lo haces, consulta los codelabs de pruebas.