简体   繁体   中英

Android Espresso flaky withId withText test

I have this test that works about half the time.

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

I get this failure:

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

So, it looks like it found the TextView with "dog 0a" , but it won't recognize it. I have looked at other questions and I do set the text with a String , this is just a few lines from my class:

private String  englishText;
englishTextView.setText(englishText);

Also, I am using allOf() . Any help would be appreciated. This view is inside of a ViewPager 's view, so I'm not sure if the test is happening before the ViewPager is idyl, but it does say it finds the view.

You're definitely on the right track with the idling issue. Espresso has no way to know when a ViewPager has fully settled after a swipe is performed. As the failure implies, the view you're looking for is somewhere in the view hierarchy, which means that it's been rendered, but Espresso is detecting that it's not on screen yet. This is because the ViewPager hasn't fully settled onto the page you're interested in.

The next question would be how to tell Espresso to wait for the ViewPager to settle. This is a somewhat tough problem to solve.

A way to eliminate the likelihood of this problem is to perform a Thread.sleep , which will force Espresso to wait for some amount of time, with the hopes that the ViewPager settles before the wait is over. While this can generally work with a large enough sleep duration, this isn't ideal as this adds unnecessary time to your tests.

The best way to go about this would be to have ViewPager tell us when it's fully done settling.

If you take a look at some of the listeners available for ViewPager, one of them is the OnPageChangeListener . This class has a couple callback methods: onPageScrolled , onPageScrollStateChanged , and onPageSelected .

onPageSelected sounds like a good candidate, but if you take a closer look at the documentation for this method, you'll notice it says

/**
 * This method will be invoked when a new page becomes selected. Animation is not
 * necessarily complete.
 */

So this isn't going to work.

onPageScrollStateChanged is another good candidate. This reports a couple state changes in ViewPager, namely, SCROLL_STATE_DRAGGING , SCROLL_STATE_SETTLING , and SCROLL_STATE_IDLE . So using this callback, we can detect when the ViewPager goes idle.

As to how to hook an instance of this listener up to the ViewPager and Espresso, you can take a look at this implementation provided by Espresso for performing actions on DrawerLayouts and similarly waiting for them to settle. The jist of it is that you create a custom ViewAction to use that attaches one of these listeners on to the ViewPager, then performs the swipe and waits for the ViewPager to report that it went into SCROLL_STATE_IDLE .

Note that this implementation uses reflection to remove and wrap a DrawerListener from the DrawerLayout if one exists before attaching it's own, but this isn't necessary in the ViewPager case, as ViewPager can have multiple OnPageChangeListeners attached to it.

this worked for me

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM