ProgressBars and Espresso

When I have a ProgressBar in the mockups that appear when I run some espresso tests, then I come across:

Caused by: android.support.test.espresso.AppNotIdleException: Looped for 1670 iterations over 60 SECONDS. The following Idle Conditions failed . 

What a good way to get around this? Found some hacking stuff but were looking for a good way

+13
android android-espresso
Oct 22 '15 at 19:30
source share
5 answers

I have the same problem. I could not understand an absolutely elegant solution, but I will also post my approach.

What I was trying to do was override indeterminateDrawable on a ProgressBar. If there is a simple animation without animation and the Espresso test, there is no problem with downtime.

Unfortunately, main and androidTest handled the same way. I did not find a way to override the styles of my ProgressBar.

Now this has led to the pooling of some ideas from https://gist.github.com/Mauin/62c24c8a53593c0a605e#file-progressbar-java and How to determine if an Android application runs a UI test using Espresso .

First, I created custom ProgressBar classes, one for debugging and one for release. The release version only calls superconstructors and does nothing. The debug version overrides the setIndeterminateDrawable method. With this, I could install a simple option, not an animated one.

Release Code:

 public class ProgressBar extends android.widget.ProgressBar { public ProgressBar(Context context) { super(context); } public ProgressBar(Context context, AttributeSet attrs) { super(context, attrs); } public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } } 

Debug Code:

 public class ProgressBar extends android.widget.ProgressBar { public ProgressBar(Context context) { super(context); } public ProgressBar(Context context, AttributeSet attrs) { super(context, attrs); } public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @SuppressWarnings("deprecation") @Override public void setIndeterminateDrawable(Drawable d) { if (isRunningTest()) { d = getResources().getDrawable(R.drawable.ic_replay); } super.setIndeterminateDrawable(d); } private boolean isRunningTest() { try { Class.forName("base.EspressoTestBase"); return true; } catch (ClassNotFoundException e) { /* no-op */ } return false; } } 

As you can see, I also added a check if my application runs the Espresso test, while the class I'm looking for is the base of my Espresso tests.

The bad news is that you need to update all your code in order to use your own ProgressBar. But it’s good that your release code does not have a significant impact on this decision.

+7
Mar 24 '16 at 13:42 on
source share

If the ProgressBar invisible when the test starts, Drawable can be replaced with a normal ViewAction :

 // Replace the drawable with a static color onView(isAssignableFrom(ProgressBar.class)).perform(replaceProgressBarDrawable()); // Click a button (that will make the ProgressBar visible) onView(withText("Show ProgressBar").perform(click()); 

Custom ViewAction :

 public static ViewAction replaceProgressBarDrawable() { return actionWithAssertions(new ViewAction() { @Override public Matcher<View> getConstraints() { return isAssignableFrom(ProgressBar.class); } @Override public String getDescription() { return "replace the ProgressBar drawable"; } @Override public void perform(final UiController uiController, final View view) { // Replace the indeterminate drawable with a static red ColorDrawable ProgressBar progressBar = (ProgressBar) view; progressBar.setIndeterminateDrawable(new ColorDrawable(0xffff0000)); uiController.loopMainThreadUntilIdle(); } }); } 
+6
Jun 16 '16 at 16:24
source share

I have a similar problem. The test failed already in the first call to getActivity (). Thus, an undefined carry ProgressBar must be replaced after the start of the action.

  Application application = (Application)this.getInstrumentation().getTargetContext().getApplicationContext(); application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { //not here, it too early } @Override public void onActivityStarted(Activity activity) { //find the progressBar in your activity ProgressBar progressBar = ((ProgressBar) activity.findViewById(R.id.progress_bar)); if(progressBar != null) { //replace progress bar drawable as not animated progressBar.setIndeterminateDrawable(new ColorDrawable(0xffff0000)); } } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } }); //Now you can start the activity getActivity(); 
+4
Nov 01 '16 at 12:35
source share

Based on Thomas R.'s solution , another approach is to modify the extraction of the ProgressBar in the test to avoid changing the production code.

Example:

  Activity activity = startActivity(); // override progress bar infinite animation with a simple image ProgressBar progressBar = (ProgressBar) activity.findViewById(R.id.loading_progressbar); progressBar.setIndeterminateDrawable(activity.getDrawable(android.R.drawable.ic_lock_lock)); // click on the button that triggers the display of the progress bar onView(withId(R.id.login_button)).perform(click()); 
+2
May 05 '16 at 11:53
source share

This answer may be belated. With espresso, you must turn off the animation.

On your device, in the "Settings"> "Developer Settings" section, disable the following 3 settings:

Window animation scale, transition animation scale, animator animation scale

https://developer.android.com/training/testing/espresso/setup.html#set-up-environment

There is an answer to the test progress bar on Android with espresso from riwnodennyk

But be careful with UIAnimator

Caution: we recommend that you test your application using the UI Automator only when your application must interact with the system to perform a critical use case. Since the Automator UI interacts with system applications and user interfaces, you need to restart the launch and correct your Automation UI tests after each system update. such updates include updates to the version of the Android platform and new versions of the Google Play Service. As an alternative to using UI Automator, we recommend adding sealed tests or separating your large test into a set of small to medium tests. In particular, focus on testing a single unified messaging between applications, for example, sending information to other applications and answers to the results of intentions. The Espresso-Intents tool can help you write these smaller tests.

https://developer.android.com/training/testing/fundamentals.html#large-tests

0
Nov 11 '17 at 15:11
source share



All Articles