【问题标题】:Espresso test fails with NoActivityResumedException oftenEspresso 测试经常因 NoActivityResumedException 而失败
【发布时间】:2015-06-02 12:42:43
【问题描述】:

编辑:更新了描述和错误信息并添加了一些图片。还是有这个问题。

我在运行 espresso 测试时多次出现一个奇怪的错误。几次成功的测试运行后,测试开始失败,但出现以下异常:

   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 脚本执行,从删除以前的应用程序和测试 api 开始,然后再次安装。确保环境清洁。日志表明卸载已成功。然后部署新应用程序并开始运行测试。现在他们失败了。

如果测试失败,直到我手动从设备中删除应用程序和测试 api,我才能再次获得成功的测试。但只有一段时间,直到发生同样的错误。

为什么我会得到 NoActivityResumedException,我找不到一个很好的例子来说明它是什么以及它何时发生。

【问题讨论】:

  • 我看过其他帖子,他们建议切换动画(在开发者设置中)。
  • 你找到解决办法了吗?
  • 不是一个明确的解决方案。但注意到它经常发生在系统窗口弹出时。当活动期望结果时也是如此。找到了一些可能适用于某些问题的答案:即stackoverflow.com/questions/21703304/…
  • 在我的情况下,正如@Pnemonic 指出的那样,动画已打开。希望这对其他人有所帮助。
  • 我的项目中有两个 android 应用程序模块,当我在运行时使用单个命令(./gradlew spoon 或 ./gradlew connectedDebugAndroidTest)在所有模块中运行测试时,在不同的测试中随机出现此错误仅测试特定模块 (./gradlew module1:connectedDebugAndroidTest) 此错误消失。不知道为什么

标签: android testing android-espresso


【解决方案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】:

    就我而言,解决方案是使用 UI Automater

    val uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
    uiDevice.findObject(UiSelector().textContains("text")).click()
    

    我想点击由 google login SDK 托管的活动。我注意到即使被测应用程序的进程被终止,SDK 触发的活动仍然可见。所以我使用了UI Automator,它用于跨应用功能 UI 测试

    【讨论】:

      【解决方案5】:

      为避免这种情况,请让您的设备保持唤醒状态。设备的开发者选项中有一个选项。

      您可以使用 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 任务激活屏幕。 (前提是没有设置密码或解锁图案)

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

      让这些任务在您负责 UI 测试的 gradle 任务之前运行。

      这样,您的测试中不需要额外的代码来激活设备并使其保持活动状态。

      【讨论】:

        【解决方案6】:

        一个可能的原因是测试并行运行。使用--no-parallel

        示例 --> gradlew connectedLiveDebugAndroidTest --no-parallel

        这仅在从控制台或顺序运行所有这些时发生,但不会单独运行它们,那么它们很可能在同一设备上并行运行。在同一设备上同时运行两个不同的 Espresso 测试会使它们变得不稳定且容易失败。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-07
          • 1970-01-01
          • 1970-01-01
          • 2014-04-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多