【问题标题】:Espresso - How can I check if an activity is launched after performing a certain action?Espresso - 如何在执行特定操作后检查活动是否启动?
【发布时间】:2014-09-23 15:12:06
【问题描述】:

以下是我的 Espresso 测试用例之一。

    public void testLoginAttempt() {
        Espresso.onView(ViewMatchers.withId(R.id.username)).perform(ViewActions.clearText()).perform(ViewActions.typeText("nonexistinguser@krossover.com"));
        Espresso.onView(ViewMatchers.withId(R.id.username)).perform(ViewActions.clearText()).perform(ViewActions.typeText("invalidpassword"));

        Espresso.onView(ViewMatchers.withId(R.id.login_button)).perform(ViewActions.click());
        // AFTER CLICKING THE BUTTON, A NEW ACTIVITY WILL POP UP.
        // Clicking launches a new activity that shows the text entered above. You don't need to do
        // anything special to handle the activity transitions. Espresso takes care of waiting for the
        // new activity to be resumed and its view hierarchy to be laid out.
        Espresso.onView(ViewMatchers.withId(R.id.action_logout))
                .check(ViewAssertions.matches(not(ViewMatchers.isDisplayed())));

    }

目前我所做的是检查新活动 (R.id.action_logout) 中的视图是否可见。如果可见,我将假设活动已成功打开。 但它似乎没有像我预期的那样工作。 有没有更好的方法来检查新活动是否成功启动,而不是检查该活动中的视图是否可见? 谢谢

【问题讨论】:

  • 为什么不导入 ViewMatchers? import static android.support.test.espresso.matcher.ViewMatchers.*
  • @user2062024 你能发布工作代码吗?
  • 最新的 Espresso 会自动等待 Asyntask。

标签: android android-activity android-espresso


【解决方案1】:

你可以使用:

intended(hasComponent(YourExpectedActivity.class.getName()));

需要这个 gradle 条目:

androidTestCompile ("com.android.support.test.espresso:espresso-intents:$espressoVersion")

intended()hasComponent() 的导入

import static android.support.test.espresso.intent.Intents.intended;
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;

如 Shubam Gupta 所述,请记得在致电 intended() 之前致电 Intents.init()。您最终可以在 @Before 方法中调用它。

【讨论】:

  • hmm,现在 android 官方文档没有提到 Intents.init() 的东西,在我的单一情况下,没有这个它可以完美地工作。那么正确的解决方案是什么?
  • 最后,你需要在@After中释放Intents,就像Intents.release()一样
  • 如果您对此不熟悉,请务必阅读下面的 Shubhams 回答。
【解决方案2】:

试试:

intended(hasComponent(YourActivity.class.getName()));

另外,请记住

如果在intended()之前没有调用Intents.init(),则抛出java.lang.NullPointerException

【讨论】:

  • 感谢您提及 init() 的事情!
【解决方案3】:

你可以这样做:

    @Test
public void testLoginAttempt() {
    Espresso.onView(ViewMatchers.withId(R.id.username)).perform(ViewActions.clearText()).perform(ViewActions.typeText("nonexistinguser@example.com"));
    Espresso.onView(ViewMatchers.withId(R.id.username)).perform(ViewActions.clearText()).perform(ViewActions.typeText("invalidpassword"));

    Intents.init();
    Espresso.onView(ViewMatchers.withId(R.id.login_button)).perform(ViewActions.click());
    Intents.release();
}

如果不调用Intents.init(),则抛出java.lang.NullPointerException

【讨论】:

    【解决方案4】:

    确保 Espresso 意图库在 gradle 依赖项中

    androidTestImplementation "com.android.support.test.espresso:espresso-intents:3.0.1"
    

    然后在你的测试文件中导入这两个

    import static android.support.test.espresso.intent.Intents.intended
    import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
    

    然后在你的测试类中添加IntentsTestRule

    @Rule
    @JvmField
    val mainActivityRule = IntentsTestRule(MainActivity::class.java)
    

    最后检查activity是否启动了intent

    @Test
    fun launchActivityTest() {
        onView(ViewMatchers.withId(R.id.nav_wonderful_activity))
                .perform(click())
    
        intended(hasComponent(WonderfulActivity::class.java!!.getName()))
    }
    

    【讨论】:

    • IntentsTestRule 现在已被弃用。您应该将上面提到的 Intents.init() 与 ActivityScenarioRule 结合使用。
    【解决方案5】:

    问题是您的应用程序在您单击登录按钮后执行网络操作。 Espresso 默认不处理(等待)网络调用以完成。您必须实现您的自定义 IdlingResource,这将阻止 Espresso 继续进行测试,直到 IdlingResource 返回空闲状态,这意味着网络请求已完成。看看 Espresso 样品页面 - https://google.github.io/android-testing-support-library/samples/index.html

    【讨论】:

    • 更新过时的链接
    【解决方案6】:

    试试

    intended(hasComponent(new ComponentName(getTargetContext(), ExpectedActivity.class)));
    

    response from @riwnodennyk

    【讨论】:

    • 为什么需要new ComponentName
    【解决方案7】:

    我使用这种方法:

    // The IntentsTestRule class initializes Espresso Intents before each test, terminates the host activity, and releases Espresso Intents after each test
        @get:Rule
        var tradersActivity: IntentsTestRule<TradersActivity> = IntentsTestRule(TradersActivity::class.java)
        @get:Rule
        var jsonViewActivity: IntentsTestRule<JsonViewActivity> = IntentsTestRule(JsonViewActivity::class.java)
    
        @Test
        fun scrollToItemAndClick() {
         onView(withId(R.id.tradersRecyclerView)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(ITEM_POS, click()))
    
            // check is activity was started
            intended(hasComponent(JsonViewActivity::class.java.getName()))
        }
    

    【讨论】:

      【解决方案8】:
      @RunWith(RobolectricTestRunner.class)
      public class WelcomeActivityTest {
      
          @Test
          public void clickingLogin_shouldStartLoginActivity() {
              WelcomeActivity activity = Robolectric.setupActivity(WelcomeActivity.class);
              activity.findViewById(R.id.login).performClick();
      
              Intent expectedIntent = new Intent(activity, LoginActivity.class);
              assertThat(shadowOf(activity).getNextStartedActivity()).isEqualTo(expectedIntent);
          }
      }
      

      【讨论】:

      • 问题是关于 Espresso,而不是 Robolectric。
      猜你喜欢
      • 2015-01-13
      • 2012-03-22
      • 1970-01-01
      • 2012-10-03
      • 2013-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多