avi rao
avi rao

Reputation: 33

How does espresso time idler behave?

I am using above technique mentioned in the blog , however I have noticed that it doesn't wait for required 15 seconds that I am trying to set. My question here, if all the backend task is completed before 15 seconds, does espresso identifies it and starts the next consecutive operations? Any leads on this is appreciated.

    public class ElapsedTimeIdlingResource implements IdlingResource {
  private final long startTime;
  private final long waitingTime;
  private ResourceCallback resourceCallback;

  public ElapsedTimeIdlingResource(long waitingTime) {
    this.startTime = System.currentTimeMillis();
    this.waitingTime = waitingTime;
  }

  @Override
  public String getName() {
    return ElapsedTimeIdlingResource.class.getName() + ":" + waitingTime;
  }

  @Override
  public boolean isIdleNow() {
    long elapsed = System.currentTimeMillis() - startTime;
    boolean idle = (elapsed >= waitingTime);
    if (idle) {
      resourceCallback.onTransitionToIdle();
    }
    return idle;
  }

  @Override
  public void registerIdleTransitionCallback(
      ResourceCallback resourceCallback) {
    this.resourceCallback = resourceCallback;
  }
    }

==

long waitingTime = DateUtils.MINUTE_IN_MILLIS / 4;

IdlingPolicies.setMasterPolicyTimeout(
    waitingTime * 2, TimeUnit.MILLISECONDS);
IdlingPolicies.setIdlingResourceTimeout(
    waitingTime * 2, TimeUnit.MILLISECONDS);

IdlingResource idlingResource 
    = new ElapsedTimeIdlingResource(waitingTime);
Espresso.registerIdlingResources(idlingResource);

Upvotes: 1

Views: 342

Answers (1)

Michael Dodd
Michael Dodd

Reputation: 10270

You will need to run an Espresso command, any Espresso command, following registerIdlingResources(). I've created this example unit test on my own PC and it works fine.

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Rule public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);

    private final long waitingTime = DateUtils.MINUTE_IN_MILLIS / 4;

    @Before public void setUp() {
        IdlingPolicies.setMasterPolicyTimeout(waitingTime * 2, TimeUnit.MILLISECONDS);
        IdlingPolicies.setIdlingResourceTimeout(waitingTime * 2, TimeUnit.MILLISECONDS);
    }

    @Test public void useAppContext() throws Exception {
        IdlingResource idlingResource = new ElapsedTimeIdlingResource(waitingTime);

        Espresso.registerIdlingResources(idlingResource);
        onView(withId(R.id.btnStart)).perform(click());
        Espresso.unregisterIdlingResources(idlingResource);

        assertTrue(true);
    }
}

Test results

In my example, I have a button called btnStart that I perform a click on, but it can be anything relevant to your app. Let me know if that works for you.


And to directly answer your further questions in the comments:

  1. isIdleNow() is constantly polled by Espresso after an Idling resource is registered. When idle is true, that's the signal for Espresso to proceed to the next command. You need isIdleNow() to return false if you want to block.
  2. In this specific case, no, the Idling Resource is purely based on time, not the state of a background process, but you can make Idling Resources that poll the state of running threads/processes. Unless your process ends by closing the activity, Espresso will wait, but will only block itself (e.g. stuff like ViewMatchers, clicks, etc), not any other threads. The activity will continue to function as normal.

Upvotes: 1

Related Questions