I am writing Instrumentation tests with usage of Espresso 2.2.
Flow I want to test:
I want to register IdleResource after click on radioButton so it waits until vSetupAmount becomes visible. But I can't make it work. Please tell me what am I doing wrong.
I have written such IdleResource:
public class AmountViewIdlingResource implements IdlingResource {
private CountriesAndRatesActivity activity;
private ResourceCallback callback;
private SetupAmountView amountView;
public AmountViewIdlingResource(CountriesAndRatesActivity activity) {
this.activity = activity;
amountView = (SetupAmountView) this.activity.findViewById(R.id.vSetupAmount);
}
@Override public String getName() {
return "Amount View idling resource";
}
@Override public boolean isIdleNow() {
callback.onTransitionToIdle();
return amountView.getVisibility() == View.VISIBLE;
}
@Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
this.callback = resourceCallback;
}
}
So I am passing activity to IdleResource, link view with variable. I understand that IdleResource won't let test go through until isIdleNow() returns value true. So if view is View.GONE then it won't go further.
How it looks in test:
// click of radioButton picked from radioGroup
onView(withId(rgDeliveries.getChildAt(id).getId())).perform(scrollTo(), click());
// wait for view to become visible
Espresso.registerIdlingResources(new AmountViewIdlingResource(getActivity()));
// go to button on view
onView(withId(R.id.btnGetStarted)).perform(scrollTo());
// unregister idle resource
for ( IdlingResource resource : getIdlingResources()) {
Espresso.unregisterIdlingResources(resource);
}
So I get my click on radioButton. IdleResource is successfully registered but nothing happens. On my device API response comes. vSetupAmount is being displayed but
amountView.getVisibility() == View.VISIBLE;
which is being checked forever (but I see my view on screen) always returns false.
What am I doing wrong?
I know this might be too late, but my answer might help someone.
AmountViewIdlingResource
, keep a reference to it and only unregister that reference, don't unregister all IdlingResources
.isIdleNow()
method should only call the callback's onTransitionToIdle()
method if your idling resource is really idle not every time.I needed to do something similar, to wait for a button to appear on the screen, which in turn only got to be visible after an HTTP call finished. My implementation of a view visibility Idling Resource is as follows:
public class ViewVisibilityIdlingResource implements IdlingResource {
private final View mView;
private final int mExpectedVisibility;
private boolean mIdle;
private ResourceCallback mResourceCallback;
public ViewVisibilityIdlingResource(final View view, final int expectedVisibility) {
this.mView = view;
this.mExpectedVisibility = expectedVisibility;
this.mIdle = false;
this.mResourceCallback = null;
}
@Override
public final String getName() {
return ViewVisibilityIdlingResource.class.getSimpleName();
}
@Override
public final boolean isIdleNow() {
mIdle = mIdle || mView.getVisibility() == mExpectedVisibility;
if (mIdle) {
if (mResourceCallback != null) {
mResourceCallback.onTransitionToIdle();
}
}
return mIdle;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
mResourceCallback = resourceCallback;
}
}
Hope this helps