Flujo crítico con Espresso y Screen Object - 1Adevelopers/FlorAppMovil GitHub Wiki

Esta sección documenta la prueba automatizada de interfaz del flujo crítico de login realizada con Espresso, organizada con el patrón Screen Object e incluyendo chequeos automáticos de accesibilidad.

Dato Valor
Herramienta Espresso 3.5.1 + espresso-accessibility 3.5.1
Lenguaje / framework Java + JUnit 4 (AndroidJUnit4)
Tipo de prueba Instrumentada de interfaz (corre en el dispositivo)
Patrón Screen Object (una clase por pantalla)
ID automatización AUT-ESP-01
Clase de test app/src/androidTest/java/com/ispc/florappmovil/flujos/LoginFlujoCriticoTest.java
Dispositivo probado Samsung Galaxy J7 Pro (SM-J730GM), Android 9, por USB
Responsable Eric Heredia
Reporte LoginFlujoCriticoTest

1. ¿Qué es cada cosa?

Espresso

Es la herramienta oficial de Google para probar la interfaz de apps Android. El test se ejecuta dentro de la app, en el dispositivo, y simula lo que haría un usuario: tocar botones, escribir y verificar lo que se ve en pantalla.

Appium (AUT-LOG-01) Espresso (AUT-ESP-01)
Dónde corre Fuera de la app, desde la PC Dentro del proyecto (androidTest)
Qué necesita Node.js, servidor Appium, driver UiAutomator2 Nada extra: viene con Android Studio
Cómo encuentra los elementos Texto del id (com.ispc.florappmovil:id/btnLogin) Directo con R.id.btnLogin
Tipo de prueba Caja negra Caja gris (conoce el código de la app)

Screen Object

Es un patrón para organizar las pruebas de interfaz: se crea una clase por pantalla que sabe cómo manejarla (qué botones tiene, cómo se completa). El test solo llama a esos métodos, por lo que se lee casi como el caso de prueba escrito:

new IngresoScreen()
        .verificarVisible()
        .tocarIniciarSesion()
        .iniciarSesion(EMAIL, PASSWORD)
        .verificarSesionActiva()
        .presionarAtras()
        .aceptarCerrarSesion()
        .verificarVisible();

Ventaja: si cambia un id en un layout, se corrige en una sola clase (la Screen) y no en todos los tests.

Flujo crítico

Es el recorrido más importante de la app: si falla, la app no cumple su función. En FlorApp es el inicio y cierre de sesión.


2. Estructura

app/src/androidTest/java/com/ispc/florappmovil/
├── screens/
│   ├── BaseScreen.java       → método común esperarVisible()
│   ├── IngresoScreen.java    → pantalla de Ingreso
│   ├── LoginScreen.java      → pantalla de Login
│   └── GaleriaScreen.java    → Galería y modal de salida
└── flujos/
    └── LoginFlujoCriticoTest.java   → el test (AUT-ESP-01)
Clase Responsabilidad Métodos
BaseScreen Base común de todas las Screens esperarVisible(): reintenta hasta 15 s hasta que una vista aparezca (Espresso no espera la respuesta del servidor Django)
IngresoScreen Pantalla de Ingreso (IngresoActivity) verificarVisible(), tocarIniciarSesion()
LoginScreen Pantalla de Login (LoginActivity) escribirEmail(), escribirPassword(), tocarIngresar(), iniciarSesion()
GaleriaScreen Galería (GaleriaActivity) y modal de salida verificarSesionActiva(), presionarAtras(), aceptarCerrarSesion()

3. Flujo automatizado (AUT-ESP-01)

Paso Acción Verificación
1 Se borra la sesión guardada y se abre la pantalla de Ingreso Se ven los botones Iniciar sesión, Registrarse e Ingresar como invitado
2 Toca "Iniciar sesión" Se abre la pantalla de Login
3 Escribe email y contraseña y toca "Iniciar sesión" —
4 Espera la respuesta del backend La barra de navegación muestra "Mi Perfil" (sesión activa)
5 Presiona "Atrás" Aparece el modal "¿Deseás cerrar sesión?"
6 Toca "Aceptar" en el modal Vuelve a la pantalla de Ingreso

Acciones de Espresso utilizadas

Código Significado
onView(withId(R.id.btnLogin)) Busca la vista con ese id
.perform(click()) La toca
.perform(typeText("..."), closeSoftKeyboard()) Escribe el texto y cierra el teclado
.check(matches(isDisplayed())) Verifica que se vea
.check(matches(withText("Mi Perfil"))) Verifica el texto exacto
pressBack() Presiona el botón Atrás del dispositivo
.inRoot(isDialog()) Busca la vista dentro del modal

4. Chequeos automáticos de accesibilidad

En el test se activa:

@BeforeClass
public static void activarChequeosDeAccesibilidad() {
    AccessibilityChecks.enable().setRunChecksFromRootView(true);
}

Desde ese momento, cada vez que el test toca o escribe algo, Espresso analiza toda la pantalla con el Accessibility Test Framework de Google. Si encuentra un problema, el test falla e indica la vista y el motivo.

Chequeo Regla
Contraste de texto Mínimo 4.5:1 (3:1 en texto grande) – WCAG 2.1, 1.4.3
Tamaño táctil Mínimo 48×48 dp – WCAG 2.1, 2.5.5 / guía de Android
Etiquetas Elementos interactivos con texto o contentDescription para TalkBack

Hallazgos y correcciones

Bug Issue Pantalla Hallazgo (chequeo) Corrección
BUG-ACC-01 #66 Login El enlace "¿No tenés cuenta? Registrate" (tvIrARegistro) medía 40dp de alto (TouchTargetSizeCheck) android:minHeight="48dp" y android:gravity="center" en activity_login.xml
BUG-ACC-02 #67 Galería La etiqueta de categoría (tvCategoria) tenía texto #FFFFFF sobre #BFBFBF: contraste 1.84:1 (TextContrastCheck) Texto @color/texto_principal (#334155) en item_ficha.xml: contraste 5.6:1

Luego de las correcciones, el flujo completo se ejecuta sin hallazgos.


5. Configuración

En app/build.gradle, dentro de dependencies:

androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.5.1'

espresso-core ya estaba en el proyecto; se agregó espresso-accessibility con la misma versión. Ambas son androidTestImplementation: solo se usan en las pruebas y no se incluyen en la app.


6. Ejecutar la prueba

Requisitos

  • Celular conectado por USB, desbloqueado y con depuración USB activada.
  • Backend Django encendido: python manage.py runserver 0.0.0.0:8000.
  • Usuario de prueba registrado: [email protected].
  • No hace falta Appium.

Desde Android Studio

Abrir LoginFlujoCriticoTest y tocar el ▶ verde junto a la clase → Run 'LoginFlujoCriticoTest'.

Desde la terminal (PowerShell, raíz del proyecto)

.\gradlew.bat :app:connectedDebugAndroidTest "-Pandroid.testInstrumentationRunnerArguments.class=com.ispc.florappmovil.flujos.LoginFlujoCriticoTest"

Informe HTML

app/build/reports/androidTests/connected/debug/index.html

Abrirlo con start app\build\reports\androidTests\connected\debug\index.html.


7. Resultado de la ejecución

Ejecución Resultado
1ª ❌ Falla por accesibilidad en Login: BUG-ACC-01 (tamaño táctil)
2ª (tras corregir Login) ❌ Falla por accesibilidad en Galería: BUG-ACC-02 (contraste)
3ª (tras corregir Galería) ✅ 1 de 1 test aprobado, sin hallazgos de accesibilidad

Ambiente: Samsung Galaxy J7 Pro (SM-J730GM), Android 9 – Backend Django local – 13/10/2026.


8. Problemas frecuentes

Síntoma Causa probable y solución
AccessibilityViewCheckException El chequeo encontró un problema real de accesibilidad. El mensaje indica la vista (res-name) y el motivo. Registrarlo como bug y corregir el layout.
NoMatchingViewException o timeout esperando "Mi Perfil" El login no respondió: revisar que Django esté encendido, la IP en local.properties y que el usuario exista.
AccessibilityChecks en rojo Falta la dependencia espresso-accessibility o el Sync Now.
Clases de la app en rojo dentro del test El archivo quedó en test en lugar de androidTest.
No aparece el reporte HTML Ejecutar desde la terminal con Gradle (el botón ▶ no siempre lo genera).

9. Cómo agregar otro flujo

  1. Si el flujo pasa por una pantalla nueva, crear su Screen en screens/ (extendiendo BaseScreen), con un método por acción.
  2. Crear el test en flujos/ encadenando los métodos de las Screens.
  3. Mantener AccessibilityChecks.enable() para revisar también la accesibilidad de las pantallas nuevas.
  4. Registrar el ID en la planilla de casos de prueba (columna "Herramienta e ID del test"), por ejemplo: Espresso + Accessibility Checks – AUT-ESP-02 (RegistroFlujoTest)