Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Espresso: How to test SwipeRefreshLayout?

My app reloads data when a down-swipe is done on a SwipeRefreshLayout. Now I try to test this with Android Test Kit / Espresso like this:

onView(withId(R.id.my_refresh_layout)).perform(swipeDown());

Unfortunately this fails with

android.support.test.espresso.PerformException: Error performing 'fast swipe'
on view 'with id: my.app.package:id/my_refresh_layout'.
...
Caused by: java.lang.RuntimeException: Action will not be performed because the target view
does not match one or more of the following constraints:
at least 90 percent of the view's area is displayed to the user.
Target view: "SwipeRefreshLayout{id=2131689751, res-name=my_refresh_layout, visibility=VISIBLE,
width=480, height=672, has-focus=false, has-focusable=true, 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=0.0, y=0.0,
child-count=2}"

Of course, the layout is visible and swiping manually works, but I'm unsure if I'm doing something wrong? The layout spans the whole screen, so it should really be possible for Espresso to do some action on it.

like image 814
Thomas Keller Avatar asked Nov 03 '15 17:11

Thomas Keller


People also ask

How do you check Espresso visibility?

One simple way to check for a View or its subclass like a Button is to use method getVisibility from View class.

What is instrumentation Espresso?

We will use Espresso; a UI test framework that creates automated tests that run on an actual device or emulator. Instrumentation tests are meant to simulate the actions of a user and allow us to test the app through the stages of the android activity lifecycle.


1 Answers

Sleeping over it sometimes helps. The underlying reason was that the to-be-swiped view was only 89% visible to the user, while Espresso's swipe actions internally demand 90%. So the solution is to wrap the swipe action into another action and override these constraints by hand, like this:

public static ViewAction withCustomConstraints(final ViewAction action, final Matcher<View> constraints) {
    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return constraints;
        }

        @Override
        public String getDescription() {
            return action.getDescription();
        }

        @Override
        public void perform(UiController uiController, View view) {
            action.perform(uiController, view);
        }
    };
}

This can then be called like this:

onView(withId(R.id.my_refresh_layout))
    .perform(withCustomConstraints(swipeDown(), isDisplayingAtLeast(85)));
like image 93
Thomas Keller Avatar answered Oct 16 '22 03:10

Thomas Keller