【问题标题】:Using Espresso idling resource with multiple activities将 Espresso 空闲资源与多个活动一起使用
【发布时间】:2014-10-17 16:14:39
【问题描述】:

我有一个启动 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];
  }

这个类在测试类中实现。

【问题讨论】:

    标签: android android-espresso


    【解决方案1】:

    这里有几个问题:

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

    您可以执行以下操作:

    1. IdlingResource 复制/粘贴到您的应用 中作为com.mycompany.IdlingResource。
    2. 然后让您的 Activity 实现该接口,并确保在对话框消失时调用 onTransitionToIdle,并确保当对话框显示时 isIdleNow 返回 false。
    3. 在您的测试代码中,编写一个“IdlingResourceAdapter”来包装 com.mycompany.IdlingResource 并将其转换为 Espresso IdlingResource 并将其注册到 Espresso。

    一旦实现了这个问题,这将变得更简单:https://code.google.com/p/android-test-kit/issues/detail?id=71

    【讨论】:

    • 如果你在 android studio 中有任何项目可以使用空闲资源,请在 github 上与(我)分享。我正在尝试使用空闲资源实现浓缩咖啡一周:((我在这里发布了我的问题 - stackoverflow.com/questions/28016562/… 但是如果有人有任何带有空闲浓缩咖啡测试的 android studio 工作项目,请分享!
    • @yogurtearl 链接现在已经过时了。你能更新它们吗?
    【解决方案2】:

    我在寻找类似答案时偶然发现了这个问题。使用 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
        ));
    }
    

    【讨论】:

      猜你喜欢
      • 2015-03-24
      • 2019-01-14
      • 1970-01-01
      • 2021-12-07
      • 1970-01-01
      • 2018-08-04
      • 2015-08-24
      • 2022-09-28
      • 1970-01-01
      相关资源
      最近更新 更多