I am creating a user interface test for an Android app. The test taps a UI element and expects another UI element to appear. The test will only pass if I include a Thread.sleep
after tapping the first UI element. How can I avoid this?
Here's the test:
@Test
public void mapInfoIsDisplayed() throws InterruptedException {
// Tap on the crosshair at the centre of the map.
onView(withId(R.id.map_crosshairs)).perform(click());
Thread.sleep(100); // Why is this required?
// Verify that the view is displayed
onView(withId(R.id.feature_title)).check(matches(isCompletelyDisplayed()));
}
The app is written in RxJava, uses Hilt for dependency injection and Espresso as the UI testing framework.
I want the test dependencies to run synchronously on the main thread so my test uses:
- the trampoline scheduler for RxJava during tests (executes on the calling thread)
- an in-memory Room database which allows queries on the main thread
I have also disabled animations through the emulator settings and have also added the following to my build.gradle
(although I'm not sure it does anything):
testOptions {
animationsDisabled = true
}
With all this I would expect the test to run synchronously, waiting for any dependent threads to finish before testing for whether my the new view is displayed. This doesn't appear to be happening so I'm left with a flaky test.
I have a strong suspicion that the production code is being executed asynchronously somewhere, the problem is I can't pinpoint where (it'd be great if there was some way in Android Studio to find this).
How can I ensure all code is executed synchronously, thus avoiding the Thread.sleep
?