Espresso how to wait for some time(1 hour)?

2019-02-06 01:54发布

In my test case I have to record for 1 hour, in robotium solo.sleep(600000) had done my work, but In espresso I am confused with IdlingResource concept. I have to start recording and wait for some time(depending on the type of test) 15mins, 60mins etc.

Equivalent code in robotium

    solo.clickOnView(solo.getView("start_record"));
    solo.sleep(duration * 60 * 1000);
    solo.clickOnView(solo.getView("stop_record"));

I tried to use it like this in espresso

@RunWith(AndroidJUnit4.class)
@SmallTest
public class AaEspressoTest {

private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.absd.rec.RecorderActivity";
private static Class<?> launcherActivityClass;
private Solo solo;
private static CoreRecordingTest skyroTestRunner;


private static Class<? extends Activity> activityClass;

static {
    try {
        activityClass = (Class<? extends Activity>) Class.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
    } catch (ClassNotFoundException e) {
        throw new RuntimeException(e);
    }
}

@Rule
public final ActivityTestRule<?> activityRule
        = new ActivityTestRule<>(activityClass);

private IntentServiceIdlingResource idlingResource;

@Before
public void registerIntentServiceIdlingResource() {
    Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
    idlingResource = new IntentServiceIdlingResource(instrumentation.getTargetContext());
    Espresso.registerIdlingResources(idlingResource);
}

@After
public void unregisterIntentServiceIdlingResource() {
    Espresso.unregisterIdlingResources(idlingResource);
}

@Test
public void testHello() throws Exception {

 onView(withId(AaEspressoTest.getId("recorderpage_record"))).perform(click());

    registerIntentServiceIdlingResource();

    onView(withId(AaEspressoTest.getId("recorderpage_stop"))).perform(click());

   }
}

Idling resource

public class IntentServiceIdlingResource implements IdlingResource {
private final Context context;
private ResourceCallback resourceCallback;
public static boolean status = false;

public IntentServiceIdlingResource(Context context) {
    this.context = context;
}

@Override
public String getName() {
    return IntentServiceIdlingResource.class.getName();
}

@Override
public boolean isIdleNow() {
    return getTimer();
}

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

}

private static boolean getTimer() {

    new CountDownTimer(5000, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            // Do Nothing
            status = false;
        }

        @Override
        public void onFinish() {             
            status = true;
        }
    };
    return status;
}
}

Exception:

android.support.test.espresso.IdlingResourceTimeoutException: Wait for [com.adbs.recorder.IntentServiceIdlingResource] to become idle timed out

3条回答
祖国的老花朵
2楼-- · 2019-02-06 02:14
@Before
public void registerIdlingResource() {
    IdlingPolicies.setMasterPolicyTimeout(60 * 1000 * 3, TimeUnit.MILLISECONDS);
    IdlingPolicies.setIdlingResourceTimeout(60 * 1000 * 3, TimeUnit.MILLISECONDS);
    mIdlingResource = BooleanIdlingResource.getIdlingResource();
    // To prove that the test fails, omit this call:
    IdlingRegistry.getInstance().register(mIdlingResource);
}

I test on my project, It works. Just setup before register idling resources. please check:

https://github.com/googlesamples/android-testing/tree/master/ui/espresso/IdlingResourceSample and

https://developer.android.com/reference/android/support/test/espresso/IdlingPolicies

查看更多
太酷不给撩
3楼-- · 2019-02-06 02:16

You need an IdlingResource with an isIdleNow() that returns true only if the specific amount of time has passed. To achieve that, save the start time and compare it with current time:

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;
  }
}

Create and register this idling resource in your test:

@Test
public static void waitForOneHour() {
  long waitingTime = DateUtils.HOUR_IN_MILLIS;

  // Start
  onView(withId(AaEspressoTest.getId("recorderpage_record")))
      .perform(click());

  // Make sure Espresso does not time out
  IdlingPolicies.setMasterPolicyTimeout(
      waitingTime * 2, TimeUnit.MILLISECONDS);
  IdlingPolicies.setIdlingResourceTimeout(
      waitingTime * 2, TimeUnit.MILLISECONDS);

  // Now we wait
  IdlingResource idlingResource = new ElapsedTimeIdlingResource(waitingTime);
  Espresso.registerIdlingResources(idlingResource);

  // Stop
  onView(withId(AaEspressoTest.getId("recorderpage_stop")))
      .perform(click());

  // Clean up
  Espresso.unregisterIdlingResources(idlingResource);
}

You need the setMasterPolicyTimeout and setIdlingResourceTimeout calls to make sure Espresso does not terminate the test due to time out.

Full example: https://github.com/chiuki/espresso-samples/tree/master/idling-resource-elapsed-time

查看更多
狗以群分
4楼-- · 2019-02-06 02:23

The default timeout that Espresso will wait for all registered resources to become idle is one minute.

You can change this using the IdlingPolicies class to set an explicit timeout:

IdlingPolicies.setIdlingResourceTimeout(1, TimeUnit.HOURS);
查看更多
登录 后发表回答