【发布时间】:2020-02-15 06:07:57
【问题描述】:
启动活动后,我的 espresso 测试失败并在 45 秒后超时。
要启动活动,我使用InstrumentationRegistry.getInstrumentation().startActivitySync(intent)。
尽管活动正确启动,但测试在 45 秒后运行超时失败。
这只是偶尔发生。
请注意,我的应用会在启动活动后立即通过OkHTTP 获取一些内容。
我也在使用像 Firebase Event Logging 这样的库。
但是,我可以确认所有 OkHTTP 请求都在 2-3 秒内完成。
阻止 Espresso 完成测试的可能原因有哪些? 如何调试此问题?
这是发生超时时的堆栈跟踪:
Thread[Jit thread pool worker thread 0,5,main]
Thread[arch_disk_io_3,5,main]
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:190)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2067)
java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1092)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
java.lang.Thread.run(Thread.java:919)
Thread[AsyncTask #1,5,main]
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:190)
java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:459)
java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:920)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1092)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
java.lang.Thread.run(Thread.java:919)
Thread[Okio Watchdog,5,main]
java.lang.Object.wait(Native Method)
okio.AsyncTimeout.awaitTimeout(AsyncTimeout.java:361)
okio.AsyncTimeout$Watchdog.run(AsyncTimeout.java:312)
Thread[Timer-1,5,main]
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:442)
java.util.TimerThread.mainLoop(Timer.java:559)
java.util.TimerThread.run(Timer.java:512)
Thread[OkHttp ConnectionPool,5,main]
java.lang.Object.wait(Native Method)
com.android.okhttp.ConnectionPool$1.run(ConnectionPool.java:106)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
java.lang.Thread.run(Thread.java:919)
Thread[RenderThread,7,main]
Thread[HeapTaskDaemon,5,system]
Thread[queued-work-looper,5,main]
android.os.MessageQueue.nativePollOnce(Native Method)
android.os.MessageQueue.next(MessageQueue.java:336)
android.os.Looper.loop(Looper.java:174)
android.os.HandlerThread.run(HandlerThread.java:67)
Thread[hwuiTask1,6,main]
Thread[ReferenceQueueDaemon,5,system]
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:442)
java.lang.Object.wait(Object.java:568)
java.lang.Daemons$ReferenceQueueDaemon.runInternal(Daemons.java:215)
java.lang.Daemons$Daemon.run(Daemons.java:137)
java.lang.Thread.run(Thread.java:919)
Thread[pool-1-thread-1,5,main]
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:230)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2109)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1132)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:849)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1092)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
java.lang.Thread.run(Thread.java:919)
Thread[OkHttp ConnectionPool,5,main]
java.lang.Object.wait(Native Method)
okhttp3.ConnectionPool$1.run(ConnectionPool.java:67)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
java.lang.Thread.run(Thread.java:919)
Thread[pool-5-thread-2,5,main]
sun.misc.Unsafe.park(Native Met
E/TestRunner: 失败: registerWithoutUI(com.myapp.RegistrationTests) ----- 开始异常 ----- E/TestRunner: java.lang.RuntimeException: 无法在 45000 秒内启动意图 Intent { act=android.intent.action.MAIN flg=0x14000000 cmp=com.myapp/com.myapp.navigation.StartupActivity }。也许主线程在合理的时间内没有空闲?可能会有动画或不断重绘屏幕的东西。或者活动是在创建时进行网络调用?请参阅线程转储日志。供您参考,在您的活动启动请求之前事件队列最后一次空闲是 1571388177991,现在队列最后一次空闲是:1571388191468。如果这些数字相同,您的活动可能会占用事件队列。 在 androidx.test.runner.MonitoringInstrumentation.startActivitySync(MonitoringInstrumentation.java:483) 在 com.myapp.TestUtilKt.launchActivity(TestUtil.kt:25) 在 com.myapp.RobotKitKt.launchStartupActivity(RobotKit.kt:18) 在 com.myappe.RobotKitKt.precondition_new_registration(RobotKit.kt:163) 在 com.myapp.RegistrationTests.registerWithoutUI(RegistrationTests.kt:48) 在 java.lang.reflect.Method.invoke(本机方法) 在 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在 androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80) 在 org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:363) 在 androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104) 在 org.junit.runners.Suite.runChild(Suite.java:128) 在 org.junit.runners.Suite.runChild(Suite.java:27) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:363) 在 org.junit.runner.JUnitCore.run(JUnitCore.java:137) 在 org.junit.runner.JUnitCore.run(JUnitCore.java:115) 在 androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56) 在 androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:392) 在 android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189) -----结束异常-----
【问题讨论】:
-
你使用 IdlingResrouces 吗? IdlingResources 现在支持
OkHttp。查找它,如果它可以正确处理调用并且不会因超时而死。 -
在我的理解中,IdlingResources 是告诉 Espresso 等待特定资源的一种手段。基本原理是避免使用 Thread.sleep()。但是,未能等待资源不是问题。这是相反的问题:Espresso 似乎在等待不空闲的资源。
-
非常正确。它不能与动画有关,也许可以尝试其他服务器实例?只有这个特定的活动吗?
-
没有动画。我现在将开始逐步禁用某些功能。但是,我真的很想从 Espresso 中提取调试信息,而不是滚动我自己的 Espresso 版本。
标签: android kotlin android-espresso ui-testing