How to make the Espresso test wait until the page loads

I will log in. After that, a request to display a list of cards. Each time this request occurs at a different time and using sleep() is not very good. How can I make the test wait as long as the page is loading? Preferably with sample code.

@RunWith(AndroidJUnit4.class)
@LargeTest
public class AuthorizationTest {

private IdlingResource mIdlingResource;

@Rule
public ActivityTestRule<AuthorizationActivity> mActivityRule = new ActivityTestRule(AuthorizationActivity.class);

@Before
public void SetUp() throws Exception {
        Thread.sleep(4000);
    try {
        onView(allOf(withId(R.id.tiAuthLogin), (isDisplayed()))).check(matches(isDisplayed()));
    } catch (NoMatchingViewException e) {
        pressBack();
    }
}


@Test
public void checkMoneyBackButton() throws Exception {
    onView(withId(R.id.btnAuthLogin)).perform(click());

    Thread.sleep(10000);
    onView(withId(R.id.etSessionKey1)).perform(typeText("1234"));
    closeSoftKeyboard();

    onView(isRoot()).perform(waitFor(40000));


    ViewInteraction viewInteraction = Espresso.onView(withText("**** 0431"));
    viewInteraction.perform(click());

    Thread.sleep(3000);

    Espresso.onView(ViewMatchers.withId(R.id.vpCard)).perform(ViewActions.swipeUp());

    onView(withId(R.id.statementMoneyBack)).check(matches(isDisplayed()));
}

}

Upvotes: 1

Views: 3945

Answers (3)

Fatur
Fatur

Reputation: 21

I think you should separate the test scenario between login and see card list. First scenario for login:

public class AuthorizationTest {
    @Rule
    public ActivityTestRule<AuthorizationActivity> mActivityRule = new ActivityTestRule(AuthorizationActivity.class);
private Activity activity;
    @Before()
    public void setup() {
        activityTestRule.launchActivity(new Intent());
        activity = activityTestRule.getActivity();
    }

    @After()
    public void tearDown() {
        activityTestRule.finishActivity();
    }
@Test
public void login() throws Exception {
    onView(withId(R.id.btnAuthLogin)).perform(click());
    onView(withId(R.id.etSessionKey1)).perform(typeText("1234"));
    closeSoftKeyboard();
    onView(isRoot()).perform(waitId(R.id.swipeRefreshLayout, 45000));
    ViewInteraction viewInteraction = Espresso.onView(withText("**** 0431"));
    viewInteraction.perform(click());
//asssert login success
onView(withId(R.id.toastloginsuccess)).check(matches(isDisplayed()));
}

Second Scenario directly into card list activity.

public class CardListTest {
    @Rule
    public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule(MainActivity.class);
private Activity activity;
    @Before()
    public void setup() {
        activityTestRule.launchActivity(new Intent());
        activity = activityTestRule.getActivity();
    }

    @After()
    public void tearDown() {
        activityTestRule.finishActivity();
    }
@Test
public void checkMoneyBackButton() throws Exception {
//assertMainActivity
onView(withId(R.id.menuTitle)).check(matches(isDisplayed()));
//Assert what you want
onView(withId(R.id.btnTransferToCard)).check(matches(isDisplayed()));
// Do what you want
}

Hope its help.

Upvotes: 0

I don’t know why, but it doesn’t work for me

@RunWith(AndroidJUnit4.class)
@LargeTest
public class AuthorizationTest {


    @Rule
    public ActivityTestRule<AuthorizationActivity> mActivityRule = new ActivityTestRule(AuthorizationActivity.class);

    @Before
    public void SetUp() throws Exception {
        Thread.sleep(4000);
    try {
        onView(allOf(withId(R.id.tiAuthLogin), (isDisplayed()))).check(matches(isDisplayed()));
    } catch (NoMatchingViewException e) {
        pressBack();
    }
}

public static ViewAction waitId(final int viewId, final long millis) {
    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return isRoot();
        }

        @Override
        public String getDescription() {
            return "wait for a specific view with id <" + viewId + "> during " + millis + " millis.";
        }

        @Override
        public void perform(final UiController uiController, final View view) {
            uiController.loopMainThreadUntilIdle();
            final long startTime = System.currentTimeMillis();
            final long endTime = startTime + millis;
            final Matcher<View> viewMatcher = withId(viewId);

            do {
                for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
                    // found view with required ID
                    if (viewMatcher.matches(child)) {
                        return;
                    }
                }

                uiController.loopMainThreadForAtLeast(50);
            }
            while (System.currentTimeMillis() < endTime);

            // timeout happens
            throw new PerformException.Builder()
                    .withActionDescription(this.getDescription())
                    .withViewDescription(HumanReadables.describe(view))
                    .withCause(new TimeoutException())
                    .build();
        }
    };
}

@Test
public void checkMoneyBackButton() throws Exception {

    onView(withId(R.id.btnAuthLogin)).perform(click());

    Thread.sleep(10000);
    onView(withId(R.id.etSessionKey1)).perform(typeText("1234"));
    closeSoftKeyboard();

    onView(isRoot()).perform(waitId(R.id.swipeRefreshLayout, 45000));


    ViewInteraction viewInteraction = Espresso.onView(withText("**** 0431"));
    viewInteraction.perform(click());

    Thread.sleep(3000);

    onView(withId(R.id.btnTransferToCard)).check(matches(isDisplayed()));
}

}

Upvotes: -2

Hieu Tran
Hieu Tran

Reputation: 53

You can create custom action to wait

Please check this link:

Android Espresso wait for text to appear

Upvotes: 0

Related Questions