使用具有多个活动的Espresso空闲资源

时间:2014-08-24 09:17:00

标签: android android-espresso

我有一个启动secondActivity的firstActivity,在secondActivity中我有一个加载对话框(不是AsyncTask),我需要让Espresso等到对话框消失后再继续测试。
我在哪里实现IdlingResource?我怎样才能让它等待dismissDialog()函数?

以下是我尝试过的事情:

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

此类在测试类中实现。

2 个答案:

答案 0 :(得分:2)

这里有一些问题:

  1. 您的isIdleNow()调用getCurrentActivity(),它调用waitForIdleSync()和runTestOnUiThread()。 isIdleNow Javadoc说:“Espresso将总是从主线程调用此方法,因此它应该是非阻塞的并立即返回。”所以这不会按原样运行,但你可以直接从isIdleNow调用getActivitiesInStage。
  2. 您的另一个问题是您存储对ResourceCallback的引用但从不调用onTransitionToIdle,您也应该允许注册多个ResourceCallback,并在所有回调上调用onTransitionToIdle。
  3. 您可以执行以下操作:

    1. IdlingResource复制/粘贴到您的应用中,如com.mycompany.IdlingResource。
    2. 然后让您的Activity实现该接口并确保在对话框消失时调用onTransitionToIdle并确保isIdleNow在对话框显示时返回false。
    3. 在您的测试代码中,编写一个“IdlingResourceAdapter”,它包装com.mycompany.IdlingResource并将其转换为Espresso IdlingResource并使用Espresso进行注册。
    4. 实施此问题后,这会更简单:https://code.google.com/p/android-test-kit/issues/detail?id=71

答案 1 :(得分:1)

我在寻找类似答案时偶然发现了这个问题。使用Stefano Dacchille关于IdlingResources的文章中的概念,我构建了以下空闲资源,等待特定Activity在激活之前处于活动状态。就我而言,我知道当存在具有特定标签的片段时,对话框会显示。这与OP的测试不同,但概念应该很好地转换。

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

要使用它,请在测试中添加与此类似的内容:

@Before
public void setUp() throws Exception {
    registerIdlingResources(new BusyWhenFragmentExistsInActivityIdlingResource(
            SomeOtherActivity.class,
            BaseActivity.LOADING_DIALOG
    ));
}
相关问题