ProgressBars和Espresso

当我在运行一些espresso测试时显示的布局中有ProgressBar时,我会遇到:

Caused by: android.support.test.espresso.AppNotIdleException: Looped for 1670 iterations over 60 SECONDS. The following Idle Conditions failed . 

解决这个问题的好方法是什么? find一些hackish东西,但寻找一个很好的方式

如果在测试开始时ProgressBar不可见,则可以使用自定义ViewAction替换Drawable

 // Replace the drawable with a static color onView(isAssignableFrom(ProgressBar.class)).perform(replaceProgressBarDrawable()); // Click a button (that will make the ProgressBar visible) onView(withText("Show ProgressBar").perform(click()); 

自定义ViewAction

 public static ViewAction replaceProgressBarDrawable() { return actionWithAssertions(new ViewAction() { @Override public Matcher getConstraints() { return isAssignableFrom(ProgressBar.class); } @Override public String getDescription() { return "replace the ProgressBar drawable"; } @Override public void perform(final UiController uiController, final View view) { // Replace the indeterminate drawable with a static red ColorDrawable ProgressBar progressBar = (ProgressBar) view; progressBar.setIndeterminateDrawable(new ColorDrawable(0xffff0000)); uiController.loopMainThreadUntilIdle(); } }); } 

我也有同样的问题。 我无法find一个完全优雅的解决方案,但我也会发布我的方法。

我试图做的是覆盖ProgressBar上的indeterminateDrawable 。 当具有简单的可绘制时,不会发生animation并且Espresso测试不会遇到空闲问题。

不幸的是, mainandroidTest被视为相同。 我没有find覆盖ProgressBar样式的方法。

它最终结合了https://gist.github.com/Mauin/62c24c8a53593c0a605e#file-progressbar-java中的一些想法以及如何检测Android应用程序是否正在使用Espresso运行UI测试 。

起初我创建了自定义ProgressBar类,一个用于调试,一个用于发布。 发布版本只调用超级构造函数而不执行任何其他操作。 调试版本会覆盖方法setIndeterminateDrawable 。 有了这个,我可以设置一个简单的drawable而不是animation。

发行代码:

 public class ProgressBar extends android.widget.ProgressBar { public ProgressBar(Context context) { super(context); } public ProgressBar(Context context, AttributeSet attrs) { super(context, attrs); } public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } } 

调试代码:

 public class ProgressBar extends android.widget.ProgressBar { public ProgressBar(Context context) { super(context); } public ProgressBar(Context context, AttributeSet attrs) { super(context, attrs); } public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @SuppressWarnings("deprecation") @Override public void setIndeterminateDrawable(Drawable d) { if (isRunningTest()) { d = getResources().getDrawable(R.drawable.ic_replay); } super.setIndeterminateDrawable(d); } private boolean isRunningTest() { try { Class.forName("base.EspressoTestBase"); return true; } catch (ClassNotFoundException e) { /* no-op */ } return false; } } 

正如您所看到的,我还添加了一个检查我的应用程序是否正在运行Espresso测试,而我正在搜索的类是我的Espresso测试的基础。

不好的是,您必须更新所有代码才能使用自定义ProgressBar。 但好处是您的发布代码对此解决方案没有重大影响。

我有类似的问题。 早在第一次调用getActivity()时测试就失败了。 因此,必须在活动开始后更换ProgressBar的不确定drawable。

  Application application = (Application)this.getInstrumentation().getTargetContext().getApplicationContext(); application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { //not here, it's too early } @Override public void onActivityStarted(Activity activity) { //find the progressBar in your activity ProgressBar progressBar = ((ProgressBar) activity.findViewById(R.id.progress_bar)); if(progressBar != null) { //replace progress bar drawable as not animated progressBar.setIndeterminateDrawable(new ColorDrawable(0xffff0000)); } } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } }); //Now you can start the activity getActivity(); 

基于Thomas R.解决方案 ,另一种方法是在测试中更改ProgressBar的drawable,以避免修改生产代码。

例:

  Activity activity = startActivity(); // override progress bar infinite animation with a simple image ProgressBar progressBar = (ProgressBar) activity.findViewById(R.id.loading_progressbar); progressBar.setIndeterminateDrawable(activity.getDrawable(android.R.drawable.ic_lock_lock)); // click on the button that triggers the display of the progress bar onView(withId(R.id.login_button)).perform(click()); 

这个答案可能会迟到。 使用浓缩咖啡,您必须关闭animation。

在您的设备上,在“设置”>“开发人员选项”下,禁用以下3个设置:

窗口animation比例,过渡animation比例,animation师持续时间比例

https://developer.android.com/training/testing/espresso/setup.html#set-up-environment

在Android上使用Espresso by riwnodennyk 测试进度条有一个答案

但要对UIAnimator保持谨慎

警告:我们建议仅在您的应用必须与系统交互以满足关键用例时才使用UI Automator测试您的应用。 由于UI Automator与系统应用程序和UI交互,因此您需要在每次系统更新后重新运行并修复UI Automator测试。 此类更新包括Android平台版本升级和新版Google Play服务。 作为使用UI Automator的替代方案,我们建议添加密封测试或将大型测试分成一套中小型测试。 特别是,专注于一次测试一个应用程序间通信,例如将信息发送到其他应用程序并响应意图结果。 Espresso-Intents工具可以帮助您编写这些较小的测试。

https://developer.android.com/training/testing/fundamentals.html#large-tests