webentwicklung-frage-antwort-db.com.de

Der Espresso-Test schlägt häufig mit NoActivityResumedException fehl

BEARBEITEN: Beschreibung und Fehlermeldung aktualisiert und einige Bilder hinzugefügt. Habe immer noch dieses Problem. 

Ich habe einen seltsamen Fehler, der oft beim Ausführen von Espresso-Tests auftritt. Nach einigen erfolgreichen Testläufen schlagen die Tests mit folgender Ausnahme fehl: 

   06-23 13:04:48.438   info    TestRunner  failed: WhenNavigatingToReportsThenCorrectViewShouldBeShown(com.myapp.ui.views.MainActivityTest)
06-23 13:04:48.439  info    TestRunner  ----- begin exception -----
06-23 13:04:48.441  info    TestRunner  Android.support.test.espresso.NoActivityResumedException: No activities in stage RESUMED. Did you forget to launch the activity. (test.getActivity() or similar)?
06-23 13:04:48.441  info    TestRunner  at dalvik.system.VMStack.getThreadStackTrace(Native Method)
06-23 13:04:48.441  info    TestRunner  at Java.lang.Thread.getStackTrace(Thread.Java:580)
06-23 13:04:48.441  info    TestRunner  at Android.support.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.Java:82)
06-23 13:04:48.441  info    TestRunner  at Android.support.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.Java:53)
06-23 13:04:48.441  info    TestRunner  at Android.support.test.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.Java:184)
06-23 13:04:48.441  info    TestRunner  at Android.support.test.espresso.ViewInteraction.doPerform(ViewInteraction.Java:115)
06-23 13:04:48.441  info    TestRunner  at Android.support.test.espresso.ViewInteraction.perform(ViewInteraction.Java:87)
06-23 13:04:48.441  info    TestRunner  at com.myapp.ui.views.MainActivityTest.WhenNavigatingToReportsThenCorrectViewShouldBeShown(MainActivityTest.Java:96)
06-23 13:04:48.441  info    TestRunner  at Java.lang.reflect.Method.invoke(Native Method)
06-23 13:04:48.441  info    TestRunner  at Java.lang.reflect.Method.invoke(Method.Java:372)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.Java:45)
06-23 13:04:48.441  info    TestRunner  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.Java:15)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.Java:42)
06-23 13:04:48.441  info    TestRunner  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.Java:20)
06-23 13:04:48.441  info    TestRunner  at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.Java:28)
06-23 13:04:48.441  info    TestRunner  at Android.support.test.internal.statement.UiThreadStatement.evaluate(UiThreadStatement.Java:55)
06-23 13:04:48.441  info    TestRunner  at Android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.Java:257)
06-23 13:04:48.441  info    TestRunner  at org.junit.rules.RunRules.evaluate(RunRules.Java:18)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.Java:263)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.Java:68)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.Java:47)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner$3.run(ParentRunner.Java:231)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.Java:60)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner.runChildren(ParentRunner.Java:229)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner.access$000(ParentRunner.Java:50)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.Java:222)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner.run(ParentRunner.Java:300)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.Suite.runChild(Suite.Java:128)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.Suite.runChild(Suite.Java:24)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner$3.run(ParentRunner.Java:231)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.Java:60)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner.runChildren(ParentRunner.Java:229)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner.access$000(ParentRunner.Java:50)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.Java:222)
06-23 13:04:48.441  info    TestRunner  at org.junit.runners.ParentRunner.run(ParentRunner.Java:300)
06-23 13:04:48.441  info    TestRunner  at org.junit.runner.JUnitCore.run(JUnitCore.Java:157)
06-23 13:04:48.441  info    TestRunner  at org.junit.runner.JUnitCore.run(JUnitCore.Java:136)
06-23 13:04:48.441  info    TestRunner  at Android.support.test.internal.runner.TestExecutor.execute(TestExecutor.Java:54)
06-23 13:04:48.441  info    TestRunner  at Android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.Java:228)
06-23 13:04:48.441  info    TestRunner  at Android.app.Instrumentation$InstrumentationThread.run(Instrumentation.Java:1837)
06-23 13:04:48.441  info    TestRunner  ----- end exception -----
06-23 13:04:48.443  info    TestRunner  finished: WhenNavigatingToReportsThenCorrectViewShouldBeShown(com.myapp.ui.views.MainActivityTest)

Ich habe eine einfache App mit Navigation zu Seiten, die an dieser Stelle nur Text enthalten, und der Test sollte zu jeder Seite navigieren und diesen Text identifizieren. 

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {

@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule(MainActivity.class);
private MainActivity mainActivity;

@Before
public void setActivity() {
    mainActivity = mActivityRule.getActivity();
}

 @Test
public void WhenNavigatingToReportsThenCorrectViewShouldBeShown() {
    onView(allOf(withId(R.id.icon), hasSibling(withText(R.string.reports)))).perform(click());

    onView(withText("This is the Reports Activity.")).check(matches(isDisplayed()));
    Spoon.screenshot(mainActivity, "main_view");
}
}

Dieser Fehler tritt nur auf dem realen Gerät auf. Bei einem emulierten Gerät funktionieren die Tests einwandfrei. Siehe Bilder unten. 

Alle Tests werden mit einem Gradle-Skript ausgeführt. Beginnen Sie mit dem Entfernen der vorherigen App und der Test-API, bevor Sie sie erneut installieren. Um eine saubere Umwelt zu gewährleisten. Das Protokoll zeigt an, dass die Deinstallation erfolgreich war. Dann stellen Sie die neue App bereit und starten Sie die Tests. Jetzt scheitern sie. 

Wenn die Tests fehlgeschlagen sind, kann ich die App und die Test-API vom Gerät manuell entfernen, um wieder erfolgreiche Tests zu erhalten. Aber nur für eine Weile, bis der gleiche Fehler auftritt. 

Warum bekomme ich NoActivityResumedException? Ich kann kein gutes Beispiel dafür finden, was es ist und wann es auftritt.

Device overview with only physical device failingFailing tests

31
peuhse

Ich hatte das gleiche Problem. Dies geschieht, wenn der Bildschirm auf dem Gerät ausgeschaltet ist. Schalten Sie den Bildschirm ein, um das Problem zu beheben.

70

Sie können Ihr Gerät vor jedem Test mit Uiautomator aufwecken.

@Before
public void init(){
     UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
     Point[] coordinates = new Point[4];
     coordinates[0] = new Point(248, 1520);
     coordinates[1] = new Point(248, 929);
     coordinates[2] = new Point(796, 1520);
     coordinates[3] = new Point(796, 929);
     try {
         if (!uiDevice.isScreenOn()) {
             uiDevice.wakeUp();
             uiDevice.swipe(coordinates, 10);
         }
     } catch (RemoteException e) {
         e.printStackTrace();
     }
}
8
Gordak

Hauptsächlich liegt der Fehler darin, dass Ihre Verbindung, wenn sie sich nicht in einem aktiven Modus befindet, nicht im Ruhezustand sein sollte, und dass sie sich auch in der App befinden muss, in der die Testfälle geschrieben wurden. Angenommen, Sie haben bereits die Startregel @Rule Activity verwendet.

2
user11479360

Eine mögliche Ursache hierfür sind die parallel laufenden Tests. Verwenden --no-parallel.

Beispiel -> gradlew connectedLiveDebugAndroidTest --no-parallel

Dies geschieht nur, wenn alle von der Konsole oder nacheinander ausgeführt werden, aber nicht einzeln, sondern wahrscheinlich parallel auf demselben Gerät. Zwei verschiedene Espresso-Tests, die gleichzeitig auf demselben Gerät ausgeführt werden, führen dazu, dass sie schuppig werden und fehleranfällig sind.

0
Sotti

Lassen Sie Ihr Gerät wach bleiben, um dies zu vermeiden. Es gibt eine Option in den Entwickleroptionen des Geräts. 

Sie können com.Android.ddmlib und eine Gradle-Task verwenden, um die Geräteeinstellungen über adb für jeden Build-Lauf und jedes Gerät, auf dem Sie testen, zu ändern.

import com.Android.ddmlib.AndroidDebugBridge
import com.Android.ddmlib.CollectingOutputReceiver
import com.Android.ddmlib.IDevice
import com.Android.ddmlib.NullOutputReceiver

task stayAwake {

    description = "Activate the Stay Awake settings in the developer options."
    group = "Device Setup"

    AndroidDebugBridge.initIfNeeded(false)
    def bridge = AndroidDebugBridge.createBridge(Android.adbExecutable.path, false)

    doLast {
        bridge.devices.each {
            it.executeShellCommand("settings put global stay_on_while_plugged_in 3", NullOutputReceiver.receiver)
            println "Device ${it} will stay awake."
        }
    }
}

Zusätzlich können Sie den Bildschirm mit einer anderen Gradelaufgabe aktivieren. (Voraussetzung ist, dass kein PIN oder Entsperrmuster eingestellt ist) 

IDevice.metaClass.inputKeyEventByShell {
    delegate.executeShellCommand("input keyevent ${it}", NullOutputReceiver.receiver)
}
IDevice.metaClass.inputSwipeByShell {
    delegate.executeShellCommand("input swipe ${it}", NullOutputReceiver.receiver)
}

task unlockScreen {

    description = "Activate screen and unlock device."
    group = "Device Setup"

    AndroidDebugBridge.initIfNeeded(false)
    def bridge = AndroidDebugBridge.createBridge(Android.adbExecutable.path, false)

    doLast {
        bridge.devices.each {

            def receiver = CollectingOutputReceiver.newInstance()
            it.executeShellCommand("dumpsys power | grep \"mHolding\"", receiver)

            def displaySuspendFalse = receiver.getOutput().find("mHoldingDisplaySuspendBlocker=false")
            def wakelockSuspendFalse = receiver.getOutput().find("mHoldingWakeLockSuspendBlocker")

            if (displaySuspendFalse || wakelockSuspendFalse) {
                it.inputKeyEventByShell('26') //power keyevent
                println "Screen of device $it activated & unlocked."
            }

            it.inputSwipeByShell('100 500 100 1450 100') //swipe action
        }
    }
}

Lassen Sie diese Aufgaben vor der für die UI-Tests zuständigen Gradel-Aufgabe laufen.

Auf diese Weise ist in Ihren Tests kein zusätzlicher Code erforderlich, um die Geräte zu aktivieren und am Leben zu erhalten.

0
KraffMann