Sunday, June 7, 2015

Espresso: Elapsed time

IdlingResource is a powerful concept in Espresso that is a little difficult to grasp. I have already written an example to wait for an IntentService to be idle, but I thought I'd write another example where it literally waits for time to pass.

Timer game

You start the timer, wait for a minute, and stop it. The game mocks you if you don't wait long enough:

If you wait for longer than a minute, the game congratulates you:

IdlingResource

To test this, we need to ask Espresso to wait. We could use SystemClock.sleep(60000), but that blocks the testing thread. Instead, we write a custom IdlingResource.

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

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

In the constructor, we save the current time, and also how long we need to wait. When Espresso wants to know if it should wait more, it calls isIdleNow(), which computes how much time has elapsed, and returns true if it is longer than the amount of time we need to wait.

Timeout policies

Besides the IdlingResource, we also need to change Espresso's timeout policies.

long waitingTime = DateUtils.SECOND_IN_MILLIS * 75;

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

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

By default, Espresso times out the app if it has been idle for 60 seconds, and times out an IdlingResource that has been idle for 26 seconds. We change the timeout policies to be twice our waiting time to make sure Espresso does not kill our test.

How does Espresso wait?

If you run this test, you will notice that the IdlingResource does not wait for the exact amount of time you specified, but slightly longer. Espresso waits by periodically checking if everything is idle, and your resource is only idle after the amount of time you specified, so it is guaranteed to wait for at least that long, but it could, and usually does, wait longer.

Full example

Check out the source code for a full example. Pay attention to see how the test cleans up by resetting the timeout policies and unregister the IdlingResource.

Source code: https://github.com/chiuki/espresso-samples/ under idling-resource-elapsed-time

Like this article? Take a look at the outline of my Espresso book and fill in this form to push me to write it! Also check out the published courses: https://gumroad.com/chiuki

1 comment:

Inline coding questions will not be answsered. Instead, ask on StackOverflow and put the link in the comment.