在Espresso Android中使用IdlingResource的正确方法

我正在用Espresso编写UI测试。 应用程序与服务器紧密配合,因此在很多情况下,我需要等待计算任一值,或者获取并显示数据等.Espresso建议使用IdlingResource。 我的IdlingResource类看起来像这样(简单明了的例子)。

public class IRViewVisible implements IdlingResource { private View view; private ResourceCallback callback; public IRViewVisible(View view) { this.view = view; } @Override public String getName() { return IRViewVisible.class.getName(); } @Override public boolean isIdleNow() { if(view.getVisibility() == View.VISIBLE && callback != null) { callback.onTransitionToIdle(); return true; } return false; } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { this.callback = resourceCallback; } } 

如果我在任何地方都错了,请纠正我(因为有时在我看来我的IdlingResources无法正常工作)。 我在setUp()注册了空闲资源,如下所示:

 IRViewVisible ir = new IRViewVisible(View v); Espresso.registerIdlingResources(ir). 

在tearDown()上取消注册。

我find了这篇文章 (有一节名为“注册一个绑定到Activity实例的组件”) – 我没有使用他的模式,但我检查了注册后(在每个方法中)设置为IdlingResource的视图的哈希码,并且它是不一样的观点 – 所有哈希都不同。

另一个问题:一个Test类(它的结果)对另一个Test类没有任何影响,可以吗?

我猜你的问题源于getName()为IRViewVisible的所有实例返回相同的名称。 这意味着您一次只能拥有一个已注册的实例 – 任何后续注册都将失败(无声!)。

您提到在每次测试结束时清除IdlingResources,但是如果要一次注册它的多个实例,则需要确保每个实例都有唯一的名称。 如果你在一次测试中注册多个IRViewVisible实例,那么你的问题就不清楚

关于你的最后一个问题:是的,这是可能的。 Android不会在测试运行之间完全关闭应用程序 – 只是活动。 可能导致问题的常见问题:

  • 无法清除持久状态(已保存的数据)。
  • 未能清除全局状态 – 例如静态variables/单例
  • 不等待后台线程完成运行。

onTransitionToIdle()值得注意的是你只能在isIdleNow()调用isIdleNow() 。 这有效(感谢@Be_Negative的抬头!)但它可能会isIdleNow()减慢您的测试速度,因为Espresso每隔几秒钟才会轮询isIdleNow() 。 如果在视图变得可见时立即调用onTransitionToIdle() ,它应该会大大加快速度。

我需要类似于你自己的IRViewVisible, 这是我的努力 。

因此,如果不设置对idlingResource的回调,isIdleNow()方法将永远不会返回true? 我认为最好像这样重构它:

 @Override public boolean isIdleNow() { boolean idle = view.getVisibility() == View.VISIBLE; if(idle && callback != null) { callback.onTransitionToIdle(); } return idle; } 

首先,您不需要使用Espresso IdlingResource来测试服务器调用。 如果您在服务器调用中使用AsyncTask ,Espresso将能够知道何时空闲,何时无空闲。 如果这还不够:尝试以这种方式重构代码:

  IRViewVisible idlingResource = new IRViewVisible(yourView); IdlingPolicies.setMasterPolicyTimeout(waitingTime * 2, TimeUnit.MILLISECONDS); IdlingPolicies.setIdlingResourceTimeout(waitingTime * 2, TimeUnit.MILLISECONDS); // Now we wait Espresso.registerIdlingResources(idlingResource); // Stop and verify // Clean up Espresso.unregisterIdlingResources(idlingResource); 

希望对你有所帮助。