Espresso-einfrieren auf-view mit looping animation
Habe ich eine Ansicht, in der ein element animiert mit den folgenden in einer Endlosschleife:
<translate
android:fromXDelta="0%"
android:toXDelta="100%"
android:duration="10000"
android:repeatCount="-1"
android:repeatMode="reverse"/>
Beim Espresso öffnet meine Tätigkeit, es ist in der Lage, einige Operationen, aber schnell friert. Ich nehme an, Espresso, warten auf den UI-thread im Leerlauf befindet, die nie passiert, in diesem Fall.
Ist der einzige Weg für mich zu testen Sie diese Ansicht, um einen Mechanismus implementieren, deaktivieren Animationen? Ich hätte eine andere Klasse Griff-Animationen, die wäre verspottet für tests. Oder build-Zeit-Bedingungen.
Bearbeiten:
Ich habe noch ein Beispielprojekt zu erstellen, zu versuchen, neu das Thema, aber hier sind ein paar weitere details in der Zwischenzeit:
1) ich bin mit Jake Wharton ' s ActivityRule
meine Aktivität automatisch gestartet (https://gist.github.com/JakeWharton/1c2f2cadab2ddd97f9fb).
2) Dies ist mein test:
onView(withId(R.id.btn_yes)).perform(click());
3) Hier ist die komplette stack-trace. Hinweis: die AppNotIdleException
:
Running tests
Test running started
android.support.test.espresso.PerformException: Error performing 'single click' on view 'with id: com.myapp:id/btn_yes'.
at android.support.test.espresso.PerformException$Builder.build(PerformException.java:83)
at android.support.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:70)
at android.support.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:53)
at android.support.test.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:185)
at android.support.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:115)
at android.support.test.espresso.ViewInteraction.perform(ViewInteraction.java:87)
at com.myapp.espresso.MyActivityTest.yesButtonTest(MyActivityTest.java:53)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at com.myapp.espresso.ActivityRule$2.evaluate(ActivityRule.java:129)
at org.junit.rules.RunRules.evaluate(RunRules.java:18)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:24)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:270)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837)
Caused by: android.support.test.espresso.AppNotIdleException: Looped for 3580 iterations over 60 SECONDS. The following Idle Conditions failed .
at android.support.test.espresso.IdlingPolicy.handleTimeout(IdlingPolicy.java:61)
at android.support.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:471)
at android.support.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:402)
at android.support.test.espresso.base.UiControllerImpl.injectMotionEvent(UiControllerImpl.java:226)
at android.support.test.espresso.action.MotionEvents.sendDown(MotionEvents.java:78)
at android.support.test.espresso.action.Tap.sendSingleTap(Tap.java:133)
at android.support.test.espresso.action.Tap.access$100(Tap.java:35)
at android.support.test.espresso.action.Tap$1.sendTap(Tap.java:40)
at android.support.test.espresso.action.GeneralClickAction.perform(GeneralClickAction.java:98)
at android.support.test.espresso.ViewInteraction$1.run(ViewInteraction.java:144)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
4) Stack-traces bei anhalten der Ausführung des Tests, während es eingefroren:
Thread #1:
"Instr: android.support.test.runner.AndroidJUnitRunner@4549" prio=5 waiting
java.lang.Thread.State: WAITING
blocks Instr: android.support.test.runner.AndroidJUnitRunner@4549
at java.lang.Object.wait(Object.java:-1)
at java.lang.Thread.parkFor(Thread.java:1220)
- locked <0x13a3> (a java.lang.Object)
at sun.misc.Unsafe.park(Unsafe.java:299)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400)
at java.util.concurrent.FutureTask.get(FutureTask.java:162)
at android.support.test.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:181)
at android.support.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:115)
at android.support.test.espresso.ViewInteraction.perform(ViewInteraction.java:87)
Thread #2:
"main@4663" prio=5 runnable
java.lang.Thread.State: RUNNABLE
at android.view.ThreadedRenderer.nSyncAndDrawFrame(ThreadedRenderer.java:-1)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:333)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2492)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2337)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1968)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.support.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:461)
at android.support.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:402)
at android.support.test.espresso.base.UiControllerImpl.injectMotionEvent(UiControllerImpl.java:226)
at android.support.test.espresso.action.MotionEvents.sendDown(MotionEvents.java:78)
at android.support.test.espresso.action.Tap.sendSingleTap(Tap.java:133)
at android.support.test.espresso.action.Tap.access$100(Tap.java:35)
at android.support.test.espresso.action.Tap$1.sendTap(Tap.java:40)
at android.support.test.espresso.action.GeneralClickAction.perform(GeneralClickAction.java:98)
at android.support.test.espresso.ViewInteraction$1.run(ViewInteraction.java:144)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java:-1)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
- Mein Verständnis ist, dass
MessageQueue
sieht sich im Leerlauf, wenn keine Nachrichten, die bereit sind, gerade jetzt, so eine unendliche animation sollte nicht verhindern, dass. Ich würde das Profil der app mit dermonitor
tool, um zu sehen, was sonst noch Los ist auf dem Haupt-thread. Vielleicht einige schlechte code ist wiederholt die Disposition selbst ohne Verzögerung. - UI-thread ist als im Leerlauf, wenn seine message-queue leer ist, oder seine getWhen() - jetzt() ist weniger als 17ms. So eine animation blockiert ui-thread. Immer noch das, was Sie beschreiben passt nicht die üblichen Symptome. Wenn der UI-thread nicht im Leerlauf für 60 Sekunden, der Espresso wird der test als nicht bestanden mit einer Ausnahme sagen so. @mieroy: Haben Sie gewartet so lange? Wenn Sie Ihren test im debug-Modus und unterbrechen der Ausführung im debugger, was ist der stack-trace, die man für die test-Durchführung thread und was ist es für app-Haupt-thread?
- Ich Hinzugefügt, um meine Frage 3 stack-traces: test-runner & main-threads während der Ausführung (Punkt #4) und der Fehler nach 60s (Punkt #3). Ich muss zugeben, ich verstehe nicht gut, wie animation, Veranstaltungen geplant sind und wie die idle-detection-Mechanismus arbeitet.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja, das problem mit dem test ist aufgrund der animation.
Die einzige Lösung, die ich denken kann, ist in der Tat das ausschalten der unendlichen Animationen.
Im Allgemeinen ist es eine gute Idee, schalten Sie die Animationen beim ausführen von funktionalen tests, wie Sie immer stellen Sie einige Verhornungen.
Ein bisschen hintergrund:
Den UI-thread wird nie im Leerlauf aus Espresso-Perspektive, weil die message-queue enthält immer ein Ereignis, das geplant ist, für die Handhabung näher als der Schwellenwert verwendet, um zu bestimmen, wenn der thread im Leerlauf ist.
Wenn man sich
QueueInterrogator
, können Sie sehen, dass esdetermineQueueState()
zurückTASK_DUE_SOON
bei der Nachrichten-queue enthält ein Ereignis, das geplant ist, für die Handhabung in weniger als 16ms.UiController
nur fortsetzen, wenn alle idle-Bedingungen erfüllt sind, im Falle derQueueInterrogator
dies ist nur der Fall, wenn die Nachrichtenwarteschlange leer ist oder die nächste Nachricht ist die geplante Behandlung in 16ms oder später.Animationen erlischt die
View
Sie transformiert werden, und dies löst eine neue view-Hierarchie-Traversierung durch dieChoreographer
. Und diese trigger-Nachricht ausViewRoot
zu denChoreographer
ist das, was ist, halten Sie Ihre UI-thread message queue nicht untätig.