Testing progress bar on Android with Espresso
As I can see Espresso
is tightly coupled with skipping dynamic UI actions whatsoever, that's why you can't test ProgressBar
using Espresso
. However, you can easily accomplish this with another Android Google tool: UiAutomator
as following:
saveButton().click(); // perform action opening ProgressBar with UiAutomator, not Espresso
assertTrue(progressBar().exists());
Using these static utils:
public static UiObject progressBar() {
return uiObjectWithText(R.string.my_progress);
}
public static UiObject saveButton() {
return uiObjectWithId(R.id.my_save_button);
}
public static UiObject uiObjectWithId(@IdRes int id) {
String resourceId = getTargetContext().getResources().getResourceName(id);
UiSelector selector = new UiSelector().resourceId(resourceId);
return UiDevice.getInstance(getInstrumentation()).findObject(selector);
}
public static UiObject uiObjectWithText(@StringRes int stringRes) {
UiSelector selector = new UiSelector().text(getTargetContext().getString(stringRes));
return UiDevice.getInstance(getInstrumentation()).findObject(selector);
}
Make sure your build.gradle
includes:
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
Espresso has problems with the animation. You can just set the drawable of the progress bar to something static just for the test and it works as expected.
Drawable notAnimatedDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.whatever);
((ProgressBar) getActivity().findViewById(R.id.progress_bar)).setIndeterminateDrawable(notAnimatedDrawable);
onView(withId(R.id.progress_bar)).check(matches(isDisplayed()));
It looks like this may not be truly possible. Though it is an older group posting, there is a fairly decisive answer in the Android Test Kit Discussion where it is stated that the UI threads don't rest during the animation of progress bars, and so the Espresso framework cannot execute.
Marcus Klepp recommends moving past this here through the use of build types. The Gradle plugin will permit you to define different build types. You could set up a different layout in your androidTest
build type which replaces the View
in question with something generic. If all you're doing is confirming that the widget isDisplayed()
under one set of conditions, and not(isDisplayed())
under another set of conditions, then you could surely implement that through different layout files. Not that it is not a little bit of a lift.
Finally, there may be another post here which carries some additional information here: "java.lang.RuntimeException: Could not launch intent" for UI with indeterminate ProgressBar