You can put an unique ID in the layout we have to check. In the example you described I would put in the login layout:
<RelativeLayout ...
android:id="@+id/loginWrapper"
...
Then, in the test you only have to check that this Id is displayed:
onView(withId(R.id.loginWrapper)).check(matches(isCompletelyDisplayed()));
I don't know if there is a better way but this one works.
And you can also wait for some time with the waitId method you can find online:
/**
* Perform action of waiting for a specific view id.
* <p/>
* E.g.:
* onView(isRoot()).perform(waitId(R.id.dialogEditor, Sampling.SECONDS_15));
*
* @param viewId
* @param millis
* @return
*/
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();
}
};
}
With this method you can do for example:
onView(isRoot()).perform(waitId(R.id.loginWrapper, 5000));
And this way the test will not fail if the login screen takes 5 seconds or less to appear.