Using the Espresso Idle Resource with Multiple Actions

I have a firstActivity that launches secondActivity, where in secondActivity I have a download dialog (not AsyncTask), and I need to make Espresso wait for the dialog to disappear before it continues the test.
Where do I need to implement IdlingResource? How can I make it wait for rejectDialog () function?

Here is what I tried to do:

class DocumentLoadingIdlingResource implements IdlingResource { private ResourceCallback callback; @Override public String getName() { return "Documnet loading idling resource"; } @Override public boolean isIdleNow() { Activity activity; try { activity = getCurrentActivity(); } catch (Throwable e) { return false; } if(activity.getClass().getName().equals(EditorActivity.class.getName()) && activity.loadingDialogShowing() == false) { return false; } return true; } @Override public void registerIdleTransitionCallback(ResourceCallback callback) { this.callback = callback; } } Activity getCurrentActivity() throws Throwable { getInstrumentation().waitForIdleSync(); final Activity[] activity = new Activity[1]; runTestOnUiThread(new Runnable() { @Override public void run() { java.util.Collection<Activity> activites = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED); activity[0] = com.google.common.collect.Iterables.getOnlyElement(activites); }}); return activity[0]; } 

This class is implemented in a test class.

+6
source share
2 answers

There are several issues here:

  • Your calls isIdleNow () getCurrentActivity (), which calls waitForIdleSync () and runTestOnUiThread (). isIdleNow Javadoc says: "Espresso will always call this method from the main thread, so it should be non-blocking and return immediately." So this will not work as it is, but you can call getActivitiesInStage directly from isIdleNow.
  • Another problem is that you keep a link to the ResourceCallback, but you never call onTransitionToIdle, you must also allow the possibility of registering multiple ResourceCallback accounts and call onTransitionToIdle in all callbacks.

You can do the following:

  • Copy / paste the IdlingResource into your application as com.mycompany.IdlingResource.
  • Then do your work with this interface and be sure to call onTransitionToIdle when the dialog disappears and make sure that isIdleNow returns false if the dialog is displayed.
  • In the test code, write "IdlingResourceAdapter", which wraps com.mycompany.IdlingResource and turns it into an Espresso IdlingResource and registers it with Espresso.

It will be easier after implementing this problem: https://code.google.com/p/android-test-kit/issues/detail?id=71

+2
source

I stumbled upon this question in search of a similar answer. Using the concepts from Stefano Dachilโ€™s article on IdlingResources , I built the following idle resource, waiting for the Activity to take an active action before starting. In my case, I know that the dialog shows when there is a fragment with a specific tag. This is not the same as the OP test, but the concepts should translate well.

 public class BusyWhenFragmentExistsInActivityIdlingResource implements IdlingResource { private FragmentActivity activity = null; private final String fragmentTag; private ResourceCallback resourceCallback; private boolean wasIdleLastTime = true; // Start off as idle private final String name; // Need this strong reference because ActivityLifecycleMonitorRegistry won't hold one private final ActivityLifecycleCallback activityLifecycleCallback; public BusyWhenFragmentExistsInActivityIdlingResource( final Class<? extends FragmentActivity> clazz, final String fragmentTag ){ name = BusyWhenFragmentExistsInActivityIdlingResource.class.getSimpleName()+" "+clazz.getSimpleName(); this.fragmentTag = fragmentTag; activityLifecycleCallback = new ActivityLifecycleCallback() { @Override public void onActivityLifecycleChanged(Activity activity, Stage stage) { if (!FragmentActivity.class.isAssignableFrom(activity.getClass())) { return; } FragmentActivity fragmentActivity = (FragmentActivity) activity; if (!clazz.isAssignableFrom(fragmentActivity.getClass())) { return; } switch (stage){ case RESUMED: BusyWhenFragmentExistsInActivityIdlingResource.this.activity = fragmentActivity; break; case STOPPED: BusyWhenFragmentExistsInActivityIdlingResource.this.activity = null; break; } } }; ActivityLifecycleMonitorRegistry.getInstance() .addLifecycleCallback(activityLifecycleCallback); } @Override public String getName() { return name; } @Override public boolean isIdleNow() { if (activity==null) { return wasIdleLastTime = true; } boolean isIdleThisTime = activity .getSupportFragmentManager() .findFragmentByTag(fragmentTag)==null; if (!wasIdleLastTime && isIdleThisTime && resourceCallback!=null){ resourceCallback.onTransitionToIdle(); } return wasIdleLastTime = isIdleThisTime; } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { this.resourceCallback = resourceCallback; } } 

To use it, add something similar to this test:

 @Before public void setUp() throws Exception { registerIdlingResources(new BusyWhenFragmentExistsInActivityIdlingResource( SomeOtherActivity.class, BaseActivity.LOADING_DIALOG )); } 
+1
source

Source: https://habr.com/ru/post/974264/


All Articles