问题
I am writing Instrumentation tests with usage of Espresso 2.2.
Flow I want to test:
- radioButton clicked by test
- onClick launches request to API
- after every time different time I receive response
- positive response triggers interface method that is called in activity
- onRequestSuccess I am making additional panel on screen named vSetupAmount visible
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?
回答1:
I know this might be too late, but my answer might help someone.
- When you instantiate and register your
AmountViewIdlingResource
, keep a reference to it and only unregister that reference, don't unregister allIdlingResources
. - Your implementation of the
isIdleNow()
method should only call the callback'sonTransitionToIdle()
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
来源:https://stackoverflow.com/questions/32995854/wait-until-view-become-visible-with-idleresource