Подтвердить что ты не робот

Тест Espresso не работает с NoActivityResumedException часто

EDIT: Обновлено описание и сообщение об ошибке и добавлены некоторые изображения. Все еще есть эта проблема.

У меня есть странная ошибка, которая возникает много раз при запуске тестов эспрессо. После нескольких успешных тестовых запусков тесты начинают сбой со следующим исключением:

   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)

У меня есть простое приложение с навигацией на страницы, содержащие текст только на этом этапе, и тест должен перейти на каждую страницу и идентифицировать этот текст.

@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");
}
}

Эта ошибка возникает только на реальном устройстве. На эмулированном устройстве тесты отлично работают. См. Изображения ниже.

Все тесты выполняются с помощью gradle script, начиная с удаления предыдущего приложения и теста api, перед его установкой. Обеспечить чистую окружающую среду. Журнал показывает, что удаление было успешным. Затем развертывание нового приложения и запуск тестов. Теперь они терпят неудачу.

Если тесты потерпели неудачу, это произойдет только после того, как я вручную удалю приложение и тест api с устройства, чтобы снова получить успешные тесты. Но только на время до тех пор, пока не произойдет такая же ошибка.

Почему я получаю NoActivityResumedException, я не могу найти хороший пример того, что это такое и когда оно происходит.

Device overview with only physical device failingFailing tests

4b9b3361

Ответ 1

У меня была та же проблема. Это происходит, когда экран на устройстве выключен. Включите экран, чтобы устранить проблему.

Ответ 2

Вы можете разбудить устройство перед каждым тестом, используя Uiautomator.

@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();
     }
}

Ответ 3

В основном ошибка заключается в том, что если ваше соединение не находится в активном режиме, оно не должно быть в спящем режиме, либо оно должно быть в приложении, где были написаны тестовые примеры. Предполагая, что вы уже использовали правило запуска @Rule Activity.

Ответ 4

Чтобы избежать этого, оставьте ваше устройство без сна. В опциях разработчика устройства есть опция.

Вы можете использовать com.android.ddmlib и задачу gradle для изменения настроек устройства через adb для каждого запуска сборки и каждого устройства, на котором вы тестируете.

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."
        }
    }
}

Кроме того, вы можете активировать экран с другой задачей Gradle. (предварительным условием является отсутствие PIN-кода или шаблона разблокировки)

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
        }
    }
}

Позвольте этим задачам выполняться перед вашей задачей Gradle, ответственной за тесты пользовательского интерфейса.

Таким образом, для активации устройств и их поддержания не требуется никакого дополнительного кода в ваших тестах.

Ответ 5

Одной из возможных причин этого являются параллельные тесты. Используйте --no-parallel.

Пример → gradlew connectedLiveDebugAndroidTest --no-parallel

Это происходит только при запуске всех из консоли или последовательно, но не происходит при их запуске по отдельности, тогда есть вероятность, что они работают параллельно на одном устройстве. Два разных теста Espresso, запущенные на одном и том же устройстве одновременно, делают их нестабильными и склонными к сбою.