安卓Espresso中的withId withText测试不稳定

4

我有一个测试,在大约一半的时间内有效。

  @Test
  public void thirdSwipe() {
    onView(withId(R.id.pager)).perform(swipeLeft());
    onView(withId(R.id.pager)).perform(swipeLeft());
    onView(withId(R.id.pager)).perform(swipeLeft());
    onView(allOf(withId(R.id.hint_english_text), withText("dog 0a"))).check(matches(isDisplayed()));
  }

我遇到了这个错误:
android.support.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: 'is displayed on the screen to the user' doesn't match the selected view.
Expected: is displayed on the screen to the user
Got: "TextView{id=2131427358, res-name=hint_english_text, visibility=VISIBLE, width=624, height=62, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=20.0, y=20.0, text=dog 0a, input-type=0, ime-target=false, has-links=false}"

看起来它找到了带有"dog 0a"TextView,但是它无法识别它。 我已经查看了其他问题,并使用String设置了文本内容,这只是我类中的几行代码:

private String  englishText;
englishTextView.setText(englishText);

另外,我正在使用allOf()。任何帮助都将不胜感激。这个视图位于ViewPager的视图中,所以我不确定测试是否在ViewPager被加载之前发生,但它确实表示找到了该视图。


是的,我已经关闭了动画。很抱歉没有提到这一点。 - flobacca
你换设备了吗?对我来说,只有棒棒糖设备才能给出正确的结果。 - Youngjae
@ozo 在滑动后和检查之前添加了一个休眠线程,但仍然不稳定。还添加了 "Flaky" 注解,但仍未生效。 - flobacca
1
@flobacca // 这个链接建议使用 waitId 方法,该方法会在规定时间内不断检查,直到该值被确认。https://dev59.com/xGEi5IYBdhLWcg3wRauf#22563297 - Youngjae
我也尝试了Chiuki的示例(在MattMatt的答案中找到),但是遇到了同样的问题,即另一个测试变得不稳定。 - flobacca
显示剩余4条评论
2个回答

6
你在解决闲置问题方面肯定是正确的。Espresso无法知道ViewPager何时完全停止滑动。正如失败所示,你要找的视图在视图层次结构中某个位置,这意味着它已经被渲染出来,但Espresso检测到它还没有显示在屏幕上。这是因为ViewPager尚未完全停留在你感兴趣的页面上。
下一个问题是如何告诉Espresso等待ViewPager稳定下来。这是一个相当棘手的问题。
消除这个问题的可能性的方法是执行Thread.sleep,这将强制Espresso等待一段时间,希望在等待结束之前ViewPager稳定下来。虽然这通常可以在足够长的休眠时间内工作,但这并不理想,因为这会在测试中添加不必要的时间。
最好的方法是让ViewPager告诉我们何时完全稳定下来。
如果你查看一些可用于ViewPager的监听器,其中之一是OnPageChangeListener。该类有几个回调方法:onPageScrolledonPageScrollStateChangedonPageSelectedonPageSelected听起来像是一个好的选择,但如果你仔细查看此方法的文档,你会注意到它说:
/**
 * This method will be invoked when a new page becomes selected. Animation is not
 * necessarily complete.
 */

所以这个方案行不通。

onPageScrollStateChanged是另一个好选择。它报告了ViewPager中的一些状态变化,即SCROLL_STATE_DRAGGINGSCROLL_STATE_SETTLINGSCROLL_STATE_IDLE。因此,使用此回调,我们可以检测到ViewPager何时进入空闲状态。

至于如何将此侦听器的实例连接到ViewPager和Espresso,您可以查看Espresso提供的这个实现,用于在DrawerLayout上执行操作并等待其稳定。主要思路是创建一个自定义的ViewAction来附加其中一个侦听器到ViewPager上,然后执行滑动并等待ViewPager报告进入了SCROLL_STATE_IDLE

请注意,此实现使用反射从DrawerLayout中删除和包装DrawerListener(如果存在),但在ViewPager情况下,这并不是必需的,因为ViewPager可以有多个OnPageChangeListener附加到它上面。


0

这对我有用

onView(allOf(
  withId(R.id.pagerimage),
  ChildOf(withId(R.id.viewpager), 0)
      )).check(matches(isDisplayed()))
        .perform(swipeLeft());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接