(4.5.5.6)Espresso的进阶: IdlingResource
Espresso 的核心是它可以与待测应用无缝同步测试操作的能力。默认情况下,Espresso 会等待当前消息队列中的 UI 事件执行(默认是 AsyncTask)完毕再进行下一个测试操作。这应该能解决大部分应用与测试同步的问题。
然而,应用中有一些执行后台操作的对象(比如与网络服务交互)通过非标准方式实现;例如:直接创建和管理线程,以及使用自定义服务。
此种情况,我们建议你首先提出可测试性的概念,然后询问使用非标准后台操作是否必要。某些情况下,可能是由于对 Android 理解太少造成的,并且应用也会受益于重构(例如,将自定义创建的线程改为 AsyncTask)。然而,某些时候重构并不现实。庆幸的是 Espresso 仍然可以同步测试操作与你的自定义资源。
这是基于idling的概念:Espresso等待app处于idle状态,才会执行下个动作和检查下个断言.
那么app处于idle状态是什么意思?Espresso检查下面几个场景:
- 在当前消息队列中没有UI事件;
- 在默认的AsyncTask线程池没有任务;
但是,如果app以其他方式执行长时间运行操作,Espresso不知道如何判断这些操作已经完成。如果是这样的话,可以通过编写自定义的IdelingResource来通知Espresso的等待时间。
idlingResource
它是一个简单的接口:
它代表了被测应用程序的资源,这个资源在测试执行时可以在后台异步工作。
接口定义了三个方法:
getName():必须返回代表idling resource的非空字符串;
isIdleNow():返回当前idlingresource的idle状态
如果返回true,onTransitionToIdle()上注册的ResourceCallback必须必须在之前已经调用;registerIdleTransitionCallback:通常此方法用于存储对回调的引用来通知idle状态的变化。
官方示例
需要入侵源代码,不做过多描述
- Espresso IdlingResource 测试延时操作的使用
自定义 示例1
问题:
点击界面某个按钮后,新出现的页面会存在一个progressDialogFragment进行网络的请求数据,直到网络异常后者请求成功才会消失
其实这个时候如何不做任何处理的话,很明显,Espresso在点击按钮后的其他操作都会失败,它肯定会报错说NoViewsMatching
所以我们需要自定义一个IdlingResource:
public class ProgressFramentIdlingResource implements IdlingResource {private FragmentManager fragmentManager;private ResourceCallback resourceCallback;public ProgressFramentIdlingResource(FragmentManager fg) {fragmentManager = fg;}@Overridepublic String getName() {return ProgressFramentIdlingResource.class.getName();}@Overridepublic boolean isIdleNow() {//通过当前页面的fragment 是否存在以及可见,来判断。for (Fragment fragment:fragmentManager.getFragments()) {if(fragment != null && fragment.isVisible()) {resourceCallback.onTransitionToIdle();return false;}}return true;}@Overridepublic void registerIdleTransitionCallback(ResourceCallback callback) {resourceCallback = callback;}
}
上面的方法是没问题的,但是问题来了,如何才能够获取到framgentManager呢。正常情况下我们只是需要activity.getSupportFragmentManager就可以解决,但是我们在Espresso中获取到的activity的对象却是上一个界面的对象,所以我们还得去有方法能够获取到当前的Acitivity。还是伟大的google帮忙了
public Activity getActivityInstance(){try {testRule.runOnUiThread(new Runnable() {public void run() {Collection<Activity> resumedActivities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);for (Activity act: resumedActivities){Log.d("Your current activity: ", act.getClass().getName());currentActivity = act;break;}}});} catch (Throwable throwable) {throwable.printStackTrace();}return currentActivity;}
上面的方法就解决了获取当前Activity的问题了,具体的使用
IdlingResource idlingResource = new ProgressFramentIdlingResource(((UpdateSubjectActivity)getActivityInstance()).getSupportFragmentManager());
Espresso.registerIdlingResources(idlingResource);
****
Espresso.unregisterIdlingResources(idlingResource);
自定义 示例2
假设你使用IntentService来做一些长时间运算,然后通过broadcast将结果返回给activity。我们希望Espresso一直等到结果返回,才来验证界面显示正确。
为了实现IdlingResource,需要重写3个函数:getName(),registerIdleTransitionCallback(),isIdleNow()
@Override
public String getName() {return IntentServiceIdlingResource.class.getName();
}@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {this.resourceCallback = resourceCallback;
}@Override
public boolean isIdleNow() {boolean idle = !isIntentServiceRunning();if (idle && resourceCallback != null) {resourceCallback.onTransitionToIdle();}return idle;
}private boolean isIntentServiceRunning() {ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);for (ActivityManager.RunningServiceInfo info : manager.getRunningServices(Integer.MAX_VALUE)) {if (RepeatService.class.getName().equals(info.service.getClassName())) {return true;}}return false;
}
idle逻辑是在isIdleNow()实现的。在这个例子中,我们通过查询ActivityManager来检查IntentService是否正在运行。如果IntentService停止运行,我们调用resourceCallback.onTransitionToIdle()来通知Espresso
为了让Espresso等待自定义的idling resource,你需要注册它。在测试代码的@Before方法中执行注册,在@After中执行注销
@Before
public void registerIntentServiceIdlingResource() {Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();idlingResource = new IntentServiceIdlingResource(instrumentation.getTargetContext());Espresso.registerIdlingResources(idlingResource);
}@After
public void unregisterIntentServiceIdlingResource() {Espresso.unregisterIdlingResources(idlingResource);
}
自定义 示例3
public class MainActivityIdlingResource implements IdlingResource {private ResourceCallback mCallback;private final long startTime;private final long waitingTime;ActivityTestRule testRule;public MainActivityIdlingResource(long waitingTime, ActivityTestRule testRule){this.startTime = System.currentTimeMillis();this.waitingTime = waitingTime;this.testRule = testRule;}@Overridepublic String getName() {return MainActivityIdlingResource.class.getSimpleName();}@Overridepublic boolean isIdleNow() {//当Activity 出现时if(ActivityUtils.getActivityInstance(testRule).getClass().getSimpleName().equals("MoaFragmentTabActivity")){mCallback.onTransitionToIdle();System.out.println("打印");return true;}return false;}@Overridepublic void registerIdleTransitionCallback(ResourceCallback callback) {this.mCallback=callback;}
}
IdlingResource idlingResource1=new MainActivityIdlingResource(1000, mActivityTestRule);Espresso.registerIdlingResources(idlingResource1);//等待主界面后执行后面的代码...Espresso.unregisterIdlingResources(idlingResource1); //等代码调试完记得关闭
自定义 示例4
public class ListAdapterIdlingResource implements IdlingResource {private IdlingResource.ResourceCallback mCallback;private final long startTime;private final long waitingTime;private ListView listView;public ListAdapterIdlingResource(long waitingTime,ListView listView){this.startTime = System.currentTimeMillis();this.waitingTime = waitingTime;this.listView=listView;}@Overridepublic String getName() {return ListAdapterIdlingResource.class.getSimpleName();}@Overridepublic boolean isIdleNow() {//当网络数据加载完,才设置适配器,故可以通过适配器是否为空值来判断其异步数据加载是否完成if(listView.getAdapter().getCount() != 0){mCallback.onTransitionToIdle();System.out.println("打印");return true;}return false;//通过时间来限制其异步加载/*long elapsed = System.currentTimeMillis() - startTime;boolean idle = (elapsed >= waitingTime);if (idle) {System.out.println("打印");mCallback.onTransitionToIdle();}return idle;*/}@Overridepublic void registerIdleTransitionCallback(ResourceCallback callback) {this.mCallback=callback;}
}
IdlingResource idlingResource = new ListAdapterIdlingResource(1000, (((PullListView) ActivityUtils.getActivityInstance(mActivityTestRule).findViewById(R.id.pull)).getRefreshableView()));//等待后台ListView加载完数据后执行后面的代码...//释放对其异步空闲处理类Espresso.unregisterIdlingResources(idlingResource);
(4.5.5.6)Espresso的进阶: IdlingResource相关推荐
- Espresso自动化测试(十一) - IdlingResource
Espresso测试有个很强大的地方是它在多个测试操作中是线程安全的.Espresso会等待当前进程的消息队列中的UI事件,并且在任何一个测试操作中会等待其中的AsyncTask结束才会执行下一个测试 ...
- 显示空闲链表和隐式空闲链表_使用空闲资源添加Espresso UI测试
显示空闲链表和隐式空闲链表 You may want to read the Spanish version of this article in Droid-Latam's publication ...
- android espresso跨程序,在Espresso Android中正确使用IdlingResource的方法
我正在用Espresso编写UI测试.应用程序与服务器紧密配合,因此在许多情况下,我需要等待任意一个值进行计算,或者获取和显示数据.Espresso建议使用IdlingResource. 我的Idli ...
- java espresso车架_Espresso UI自动化测试框架
前言 Espresso是谷歌大力推荐的一套测试框架,从Android studio2.2版本开始,google就开始支持在as上espresso自动生成单元测试代码. Espresso测试运行速度很快 ...
- Espresso Idling Resource
前沿 上一篇进行Espresso 安装方面介绍,也就是测试环境的设置.下面几篇会对照官方文档进行一个分析.避免与主题脱节.关于Espresso文章不分先后. 1.翻译官网文档 Espresso的核心是 ...
- 使用espressos idlingresource获得最高的Android测试速度
When you first start learning UI testing with Espresso, it begins fairly quickly and easily by codin ...
- Espresso IdlingResource 测试延时操作的使用
在Espresso 自动化测试的使用中已经把一些基本的测试使用方法告诉大家了,单是数据加载之类的延时操作却没有详细说明,这篇文介绍下Espresso 延时操作的使用 之前有在谷歌搜索相关资料,确实有不 ...
- 【Android进阶】20、音频播放:SoundPool 类、单元测试:Espresso框架
文章目录 20.1 创建 SoundPool 20.2 访问 assets 20.3 加载音频文件 20.4 播放音频 20.5 单元测试 20.6 创建测试类 20.7 配置测试类 20.8 编写测 ...
- android测试篇(三)单元测试之UI测试 Espresso学习与实践
前言 上一章并没有说仪器化测试,仪器化测试存放在src/androidTest目录中,仪器化测试即UI测试. 本文并没有多加理解,按照Android UI 测试指南之 Espresso抄袭(会标注转载 ...
最新文章
- Win7/Win8 系统下安装Oracle 10g 提示“程序异常终止,发生未知错误”的解决方法...
- rhel6编译ssh的src.rpm包并修改spec参数
- javaScript基本功001
- shell脚本[] [[]] -n -z 的含义解析
- Matlab的内部常数
- cmenu 隐藏子项中的一个子项_QML中的模型-视图-代理
- 12位18Bb20计算公式c语言,C语言的一些简单题目,没有答案,哪位大神帮忙做一下!!!...
- SAP ABAP实用技巧介绍系列之could not create BAdI implementation
- 你买过假芯片吗?元器件专家为您揭秘假冒芯片的套路!
- Mysql-索引的基础和类型
- 图灵社区 : 阅读 : 谁说Vim不是IDE?(三)
- LeetCode 256. 粉刷房子(DP)
- 计算机系统账户被锁定,帐号已经被系统锁定是什么意思
- 手把手教你制作AppPreview视频并上传到appStore进行审核
- 三星刷完机后一直停留在Samsung页面
- windows各类密码搜集
- TiddlyWiki笔记入门之多维度标签--发散思维与收敛思维的乐园。
- matlab程序 直线插补,无聊写matlab仿真直线插补算法
- java secretkey用法_Java SecretKeyFactory.generateSecret方法代码示例
- Flowable入门系列文章11 - Flowable API 01
热门文章
- 狄利克雷卷积_狄利克雷卷积学习笔记
- Vue实现动态路由导航
- emwin添加图标和图片
- 互联网络业的十大发展趋势
- Ubuntu 9.10 如何安装rais环境
- 百事可乐AI人工智能生产过程破光
- 软件测试类型——集成测试
- Design contains shelved or modified (but not repoured) polygons. The result of DRC is not correct.
- Python自动抢红包,从此再也不会错过微信红包了!
- 计算机怎黑夜模式么启动,Win10系统电脑夜间模式怎么开启/关闭的方法