安卓UI测试在模拟器上使用意式浓缩咖啡+MockK与SIGSEGV崩溃,在物理设备上很好



我刚刚开始使用MockK模拟基于MVP的应用程序中的所有存储库/服务逻辑,用于UI测试。

我有一些UI测试运行登录活动,Espresso输入登录名和密码,使用MockK我可以伪造各种登录失败或不成功的情况。

所有服务&存储库是标准的Kotlin对象,所以我使用mockkobjectevery/coEvery来覆盖和处理登录请求&任务。

在我的物理设备上,测试完全没有问题,但当我试图在运行Android p+的模拟器上运行推荐图像时,它们就会随机崩溃。在极少数情况下,它们能存活足够长的时间来工作。

查看日志,我得到了各种SIGSEGV:

A/libc:致命信号11(SIGSEGV),代码1(SEGV_MAPERR),tid 10425中的故障地址0x0(e.android.debug),pid 10425(e.andrio.debug)

A/libc:致命信号11(SIGSEGV),代码1(SEGV_MAPERR),tid 10968中的故障地址0xc(HeapTaskDaemon),pid 10957(e.android.debug)

A/libc:致命信号11(SIGSEGV),代码1(SEGV_MAPERR),tid 15050中的故障地址0x0(firebase instal),pid 14972(e.android.debug)

A/libc:致命信号11(SIGSEGV),代码1(SEGV_MAPERR),tid 8902中的故障地址0xd(Measurement Wor),pid 8858(e.android.debug)

A/libc:致命信号11(SIGSEGV),代码1(SEGV_MAPERR),tid 22004中的故障地址0x0(Binder:21832_5),pid 21832(e.android.debug)


但深入查看日志,我相信我找到了罪魁祸首:

InputDispatcher:通道"9fa7335 my.company.com.android.debug/my.company.com.ui.login.LoginActivity(服务器)"~通道已不可恢复地中断,将被处理!

正在寻找解决方案,似乎这可能是由于内存泄漏?

在任何情况下,我都确保在@Before方法中启动测试中的活动,在@After方法中清除此类模拟和验证时,所有模拟都会发生。

很明显,我相信测试确实很好,但Espresso或所有出现的嘲笑肯定出了问题。。。

[编辑1]

进一步查看以前的日志,这可能是内存泄漏的原因:

ActivityThread:Service com.google.android.gms.autofill.Service.AutofillService已泄露IntentReceivercom.google.android.gms.autofill.smsretriever.TracingSmsBroadcastReceiver@ce00658最初在这里注册的。是否缺少对unregisterReceiver()的调用?android.app.IntentReceiverLeaked:Service com.google.android.gms.autofill.Service.AutofillService已泄露IntentReceivercom.google.android.gms.autofill.smsretriever.TracingSmsBroadcastReceiver@ce00658最初在这里注册的。是否缺少对unregisterReceiver()的调用?

我禁用了模拟器上的AutoFillService(在相关设置部分设置为none)。这似乎在一开始就提高了我的测试成功率,但在几次运行后,它们不断崩溃。不过,现在日志不再显示此泄漏。

[编辑2]

显然,这个问题可能与MockK有关,因为我能够检索到更多的日志:

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!

经过进一步调查,安卓测试Github回购上有一个1年前的问题显示出同样的问题(但问题现已关闭):https://github.com/android/android-test/issues/352

Mock的一个相关问题在这里打开:https://github.com/mockk/mockk/issues/466

[编辑3]

我在探索回到Mockito的替代方案,它有着更多的历史和更积极的发展。这花了一些时间,但我把UI测试迁移到Mockito没有什么大问题。

结果:好吧,起初崩溃完全消失了。我可以一口气完成10次、20次、30次测试。至少在手机上是这样。

然而,在安卓电视上(仍然有模拟器),崩溃很快又出现了。然后也在移动设备上,但很少有来自InputDispatcher的可怕消息。

在设置迁移到Mockito时,我注意到Mockk有相同的限制&在Android测试仪器上进行模拟时与Mockito的依赖关系。我面临着同样的问题和困难。

因此,这让我相信,它们都不是罪魁祸首,但很可能是Android Instrumentation API。

我还注意到手动重新启动模拟器大大改善了这种情况。

这是在我的堆栈中:

W  Unexpected CPU variant for X86 using defaults: x86
ActivityThread  W  Package uses different ABI(s) than its instrumentation:

切换到64位模拟器解决了此问题。

我的仪器测试套件也遇到了这个问题,我还怀疑MockK(至少部分)有故障。

这远不是一个真正的解决方案,但我注意到,使用Android Test Orchestrator运行我的测试大大降低了由于测试进程崩溃(由上述segfault引起)而随机失败的几率。(如果您使用Firebase Test Lab模拟器运行测试,这可能特别有用。)使用Orchestrator的另一个好处是,如果您的测试在Orchestraor进程中失败,它可以很好地挖掘日志(在Firebase测试实验室中)以找到根本错误。

我不确定这是否对每个人都有效,但如果有效,很可能表明MockK(如果它真的是这个问题的根源)没有完全清理干净,而是泄漏到其他测试中。

我遇到了完全相同的情况,我的测试在Emulator上随机崩溃,Process crashed错误显示检查Logcat。Logcat上存在SIGSEGV错误,但并非总是如此。

在我的案例中,是com.linkedin.dexmaker:dexmaker-mockito-inline导致了随机崩溃。我不得不添加它来模拟Instrumentation测试中的Kotlin数据类,毕竟我不需要它。因此,消除这种依赖关系解决了我的问题。

我建议调查一下你的测试在什么时候开始崩溃,然后会更容易找到它的底部

最新更新