Acabo de empezar a usar MockK para simular toda la lógica de Repositorios/Servicios en una aplicación basada en MVP para pruebas de interfaz de usuario.
Tengo algunas pruebas de interfaz de usuario que ejecutan una actividad de inicio de sesión en la que Espresso ingresa los inicios de sesión y las contraseñas y, al usar MockK, puedo simular varias situaciones en las que el inicio de sesión falla o no.
Todos los servicios y repositorios son objetos estándar de Kotlin, por lo que estoy usando mockkobject y every/coEvery para anular y manejar las solicitudes y tareas de inicio de sesión.
En mis dispositivos físicos, no hay ningún problema con las pruebas, pero tan pronto como traté de ejecutarlas en un emulador que ejecuta Android P+ con la imagen recomendada, fallan constantemente en un momento aleatorio. Y en raras ocasiones pueden sobrevivir lo suficiente para trabajar.
Mirando los registros, obtuve varios SIGSEGV:
A/libc: señal fatal 11 (SIGSEGV), código 1 (SEGV_MAPERR), dirección de falla 0x0 en tid 10425 (e.android.debug), pid 10425 (e.android.debug)
A/libc: señal fatal 11 (SIGSEGV), código 1 (SEGV_MAPERR), dirección de falla 0xc en tid 10968 (HeapTaskDaemon), pid 10957 (e.android.debug)
A/libc: Señal fatal 11 (SIGSEGV), código 1 (SEGV_MAPERR), dirección de falla 0x0 en tid 15050 (firebase-instal), pid 14972 (e.android.debug)
A/libc: señal fatal 11 (SIGSEGV), código 1 (SEGV_MAPERR), dirección de falla 0xd en tid 8902 (Measurement Wor), pid 8858 (e.android.debug)
A/libc: Señal fatal 11 (SIGSEGV), código 1 (SEGV_MAPERR), dirección de falla 0x0 en tid 22004 (Binder:21832_5), pid 21832 (e.android.debug)
Pero mirando más profundamente en los registros, creo que encontré al culpable:
InputDispatcher: canal '9fa7335 my.company.com.android.debug/my.company.com.ui.login.LoginActivity(server)' ~ ¡El canal está roto de forma irrecuperable y será eliminado!
Buscando soluciones, parece que esto podría suceder debido a pérdidas de memoria.
En cualquier caso, me aseguré de iniciar la actividad bajo prueba en un método @Before donde ocurren todos los simulacros mientras los borro y verifico en el método @After .
Claramente, creo que las pruebas funcionan bien, pero algo debe estar mal con Espresso o con todas las burlas que ocurren...
Mirando más a fondo los registros anteriores, esta podría ser la razón por la que hay pérdidas de memoria:
ActivityThread: el servicio com.google.android.gms.autofill.service.AutofillService ha filtrado IntentReceiver com.google.android.gms.autofill.smsretriever.TracingSmsBroadcastReceiver@ce00658 que se registró originalmente aquí. ¿Te falta una llamada para unregisterReceiver()? android.app.IntentReceiverLeaked: el servicio com.google.android.gms.autofill.service.AutofillService ha filtrado IntentReceiver com.google.android.gms.autofill.smsretriever.TracingSmsBroadcastReceiver@ce00658 que se registró originalmente aquí. ¿Te falta una llamada para unregisterReceiver()?
Deshabilité AutoFillService (establecido en ninguno en la sección de configuración relevante) en mi emulador. Esto pareció mejorar la tasa de éxito de mis pruebas al principio, pero siguen fallando después de varias ejecuciones. Sin embargo, ahora los registros ya no muestran esta fuga.
Aparentemente, este problema podría estar relacionado con MockK, ya que pude recuperar más registros:
2020-07-24 11:57:15.955 15767-15780/com.my.company.android.debug A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 15780 (HeapTaskDaemon), pid 15767 (e.android.debug) 2020-07-24 11:57:15.997 15962-15962/? E/crash_dump32: failed to detach from thread 15773: No such process 2020-07-24 11:57:15.997 15962-15962/? E/crash_dump32: failed to detach from thread 15778: No such process 2020-07-24 11:57:15.997 15962-15962/? E/crash_dump32: failed to detach from thread 15779: No such process 2020-07-24 11:57:15.997 15962-15962/? E/crash_dump32: failed to detach from thread 15780: No such process // 20 more times of exact same line // 2020-07-24 11:57:16.007 15962-15962/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 2020-07-24 11:57:16.007 15962-15962/? A/DEBUG: Build fingerprint: 'google/sdk_gphone_x86/generic_x86:10/QSR1.190920.001/5891938:user/release-keys' 2020-07-24 11:57:16.007 15962-15962/? A/DEBUG: Revision: '0' 2020-07-24 11:57:16.007 15962-15962/? A/DEBUG: ABI: 'x86' 2020-07-24 11:57:16.008 15962-15962/? A/DEBUG: Timestamp: 2020-07-24 09:57:16+0000 2020-07-24 11:57:16.008 15962-15962/? A/DEBUG: pid: 15767, tid: 15780, name: HeapTaskDaemon >>> com.my.company.android.debug <<< 2020-07-24 11:57:16.008 15962-15962/? A/DEBUG: uid: 10136 2020-07-24 11:57:16.008 15962-15962/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 2020-07-24 11:57:16.008 15962-15962/? A/DEBUG: Cause: null pointer dereference 2020-07-24 11:57:16.008 15962-15962/? A/DEBUG: eax 00000000 ebx ef8a6c34 ecx 00000000 edx f310b604 2020-07-24 11:57:16.008 15962-15962/? A/DEBUG: edi f3200380 esi 00000000 2020-07-24 11:57:16.008 15962-15962/? A/DEBUG: ebp e659d9a8 esp e659d940 eip ef7d89f4 2020-07-24 11:57:16.027 2044-2135/? E/InputDispatcher: channel '342ebda com.my.company.android.debug/com.my.compan.android.ui.error.LoginActivity (server)' ~ Channel is unrecoverably broken and will be disposed!Después de una mayor investigación, hay un problema de 1 año en el repositorio de Android Test Github que muestra el mismo problema (pero el problema ahora está cerrado): https://github.com/android/android-test/issues/352
Se abrió un problema relevante en Mockk aquí: https://github.com/mockk/mockk/issues/466
Estaba explorando la alternativa de volver a Mockito que tiene más historia y un desarrollo más activo. Me llevó un poco de tiempo, pero no tuve ningún problema importante al migrar mis pruebas de interfaz de usuario a Mockito.
Los resultados: bueno, al principio el accidente desapareció por completo. Podría disparar mis pruebas, 10, 20, 30 veces sin problemas. Al menos en el móvil.
Sin embargo, en Android TV (todavía con un simulador), el bloqueo reapareció con bastante rapidez. Y luego también en dispositivos móviles, pero con mucha menos frecuencia con el terrible mensaje de InputDispatcher .
Al configurar la migración a Mockito, noté que Mockk comparte las mismas restricciones y dependencias con Mockito cuando se burla de la instrumentación de prueba de Android. Enfrenté los mismos problemas y las mismas dificultades.
Así que me llevó a creer que ninguno de ellos es el culpable, pero muy bien podrían ser las API de instrumentación de Android.
También noté que reiniciar manualmente los emuladores mejoró mucho la situación.
Esto estaba en mi stacktrace:
W Unexpected CPU variant for X86 using defaults: x86 ActivityThread W Package uses different ABI(s) than its instrumentation:Cambiar a un emulador de 64 bits solucionó el problema.
Yo también me he encontrado con este problema con mi conjunto de pruebas de instrumentación y también sospecho que MockK tiene (al menos parcialmente) la culpa.
Esto está lejos de ser una verdadera solución, pero he notado que ejecutar MIS pruebas con Android Test Orchestrator reduce en gran medida la posibilidad de fallas aleatorias debido a un bloqueo del proceso de prueba (causado por la falla de segmento anterior). (Si está ejecutando pruebas con emuladores de Firebase Test Lab, esto podría ser particularmente útil). Otra ventaja de usar Orchestrator, hace un muy buen trabajo al buscar en los registros (en Firebase Test Lab) para encontrar el error raíz si su prueba falla en un proceso de Orchestrator.
No estoy seguro de que esto funcione bien para todos, pero si lo hace, es probable que indique que MockK (si realmente es la fuente de este problema) no se está limpiando por completo y se está filtrando a otras pruebas.
Tuve exactamente el mismo caso en el que mis pruebas fallaban aleatoriamente en el emulador con un error de bloqueo del Process crashed que decía verificar el Logcat. Hubo un error SIGSEGV en Logcat, pero no siempre.
En mi caso, fue com.linkedin.dexmaker:dexmaker-mockito-inline el que provocó los bloqueos aleatorios. Tuve que agregarlo para simular una clase de datos de Kotlin en las pruebas de instrumentación que, después de todo, no necesitaba. Entonces, eliminar esta dependencia resolvió mi problema.
Recomiendo investigar después de qué punto sus pruebas comenzaron a fallar, entonces será más fácil llegar al fondo.