自己和Android的自动化测试已经打了3年交道有余,却一直没有详细了解一下robotium,最近终于抽出时间阅读了其源码,把收获好好记录一番。
众所周知,Robotium是基于Android的单元测试框架Instrumentation,而robotium对于Instrumentation封装的比较强的地方便是控件搜索,因此首先先来了解一下在robotium中控件的搜索原理,这部分的源码主要位于ViewFetcher.java中。
1.mViews的获取
要先搜索控件,必须先得到Activity的rootView。在Android中,对于一般的Activity或其对话框,其rootView叫做DecorView,其实就是Activity和Dialog外面的那层框(关于Activity或dialog的层次可以用HierarchyViewer来查看)。
虽然通过Activity类的getWindow().getDecorView可以获取到Activity自身的DecorView,但是无法获取到对话框的,因此Robotium中界面控件是从WindowManagerGlobal(或WindowManagerImpl)中的mViews获取到的。当然mViews中不但包含DecorView,还包含同进程内的所有界面的根节(如悬浮框的根节点)。mView的值的获取过程主要如下:
1) 确定mViews所在类:android 4.2之前,获取类为android.view.WindowManagerImpl,4.2及之后,获取类为WindowManagerGlobal
String windowManagerClassName; if (android.os.Build.VERSION.SDK_INT >= 17) { windowManagerClassName = "android.view.WindowManagerGlobal"; } else { windowManagerClassName = "android.view.WindowManagerImpl"; } windowManager = Class.forName(windowManagerClassName)
2). 获得类的实例:此类是个单例类,有直接的静态变量可以获取到其实例, 4.2及之后的版本其变量名为sDefaultWindowManager,3.2至4.1,其变量名为sWindowManager,3.2之前,其变量名为mWindowManager。
/** * Sets the window manager string. */ private void setWindowManagerString(){ if (android.os.Build.VERSION.SDK_INT >= 17) { windowManagerString = "sDefaultWindowManager"; } else if(android.os.Build.VERSION.SDK_INT >= 13) { windowManagerString = "sWindowManager"; } else { windowManagerString = "mWindowManager"; } }
3). 获取mViews变量的值了,从4.4开始类型变为ArrayList<View>,之前为View[]
viewsField = windowManager.getDeclaredField("mViews"); instanceField = windowManager.getDeclaredField(windowManagerString); viewsField.setAccessible(true); instanceField.setAccessible(true); Object instance = instanceField.get(null); View[] result; if (android.os.Build.VERSION.SDK_INT >= 19) { result = ((ArrayList<View>) viewsField.get(instance)).toArray(new View[0]); } else { result = (View[]) viewsField.get(instance); }
2.mViews的过滤
mViews中会包含三种类型的View:
1) 当前显示的以及没有显示的Activity的DecorView
2) 当前对话框的DecorView
3) 悬浮框View等其他不属于DecorView的独立View
在搜索控件时,显然需要在最上层界面中搜索,所以搜索范围为:
最上层的Activity/Dialog + 悬浮框
对于悬浮框,robotium中的处理是找出mViews中不属于DecorView类的View,并将其所有子控件引入。
private final View[] getNonDecorViews(View[] views) { View[] decorViews = null; if(views != null) { decorViews = new View[views.length]; int i = 0; View view; for (int j = 0; j < views.length; j++) { view = views[j]; if (view != null && !(view.getClass().getName() .equals("com.android.internal.policy.impl.PhoneWindow$DecorView"))) { decorViews[i] = view; i++; } } } return decorViews; }
对于Activity/Dialog的筛选,Robotium采取对比DrawingTime的方法选出最后绘制的DecorView,其即为最上层Activity/Dialog的DecorView:
/** * Returns the most recent view container * * @param views the views to check * @return the most recent view container */ private final View getRecentContainer(View[] views) { View container = null; long drawingTime = 0; View view; for(int i = 0; i < views.length; i++){ view = views[i]; if (view != null && view.isShown() && view.hasWindowFocus() && view.getDrawingTime() > drawingTime) { container = view; drawingTime = view.getDrawingTime(); } } return container; }
3.控件过滤&控件列表生成
得到悬浮框的根节点和最上层的DecorView后,robotium会将所有View统一添加到一个ArrayList中生成控件列表。添加方法本身很简单,就是一个简单的递归,但需要注意的是此处有一个onlySufficientlyVisible的判断。onlySufficientlyVisible是ViewFetcher中最常见的一个变量,其表示是否过滤掉显示不完全的控件,即onlySufficientlyVisible为true时表示只在显示完全的控件中搜索目标,为false时表示在所有控件中搜索目标。具体代码为下面的addChildren函数:
private void addChildren(ArrayList<View> views, ViewGroup viewGroup, boolean onlySufficientlyVisible) { if(viewGroup != null){ for (int i = 0; i < viewGroup.getChildCount(); i++) { final View child = viewGroup.getChildAt(i); if(onlySufficientlyVisible && isViewSufficientlyShown(child)) views.add(child); else if(!onlySufficientlyVisible) views.add(child); if (child instanceof ViewGroup) { addChildren(views, (ViewGroup) child, onlySufficientlyVisible); } } } }从上面的代码可以看出,当onlySufficientlyVisible为true时,robotium会对控件的可见不可见进行检查。不过这里的可见不可见不是指Visible或Invisible(Robotium过滤Invisible控件的方法是RobotiumUtils.removeInvisibleViews,原理是利用view.isShown()方法),而是指由于界面滚动而导致的没有显示或显示不完全。继续看Robotium对SufficientlyVisible是怎么判断的:
public final boolean isViewSufficientlyShown(View view){ final int[] xyView = new int[2]; final int[] xyParent = new int[2]; if(view == null) return false; final float viewHeight = view.getHeight(); final View parent = getScrollOrListParent(view); view.getLocationOnScreen(xyView); if(parent == null){ xyParent[1] = 0; } else{ parent.getLocationOnScreen(xyParent); } if(xyView[1] + (viewHeight/2.0f) > getScrollListWindowHeight(view)) return false; else if(xyView[1] + (viewHeight/2.0f) < xyParent[1]) return false; return true; }
相关推荐
robotium 最新版本5.0.1 robotium-solo-5.0.1.jar
Robotium Solo 5.0.1 版本的源码提供了深入理解其工作原理的机会,这对于开发者和测试工程师来说是极其宝贵的资源。这个压缩包文件"robotium-solo-5.0.1-sources.zip"包含了 Robotium Solo 5.0.1 版本的所有源代码,...
虽然Spring Boot不在这个源码包中,但Spring 5.0.1源码有助于理解Spring Boot的工作原理,因为它们共享很多基础组件。 通过研究Spring 5.0.1的源码,开发者不仅可以深入理解框架的工作机制,还能学习到优秀的软件...
ExtJs5.0.1官方源码,方便找不到历史版本代码的同学。
PotaPoco 5.0.1最新版源码。 如:Insert时返回的不是true,而是1了。
FFmpeg的强大之处在于其灵活性和可扩展性,用户可以根据需求自定义参数,实现复杂的多媒体处理任务。同时,FFmpeg还广泛应用于服务器端的直播系统、视频处理软件以及自动化脚本中,是多媒体处理领域不可或缺的工具。
robotium 最新版本5.0.1 robotium-solo-5.0.1.jar
《深入解析Android 5.0.1 (API 21) 源码》 Android 5.0.1 (API 21) 是Google在2014年底推出的一个重要版本,它带来了诸多新特性、性能优化以及用户体验的提升。这次更新不仅涉及系统的底层框架,还对用户界面和应用...
Elasticsearch是一款开源的全文搜索引擎,它以其高效、可扩展性以及...通过对Elasticsearch 5.0.1源码的深入研究,开发者不仅可以理解其工作原理,还能根据需求进行定制化开发,提升搜索和分析解决方案的效率和质量。
【74CMS_v5.0.1后台RCE分析】主要涉及的是74CMS内容管理系统的一个远程代码执行(Remote Code Execution, RCE)漏洞。这个漏洞发生在系统的后台管理部分,需要用户具有管理员权限才能利用。漏洞的触发点在于系统允许...
源码解析可以帮助我们理解View的绘制流程、触摸事件处理,以及动画引擎的工作方式,有助于创建更具视觉吸引力的应用。 五、系统服务与权限管理 Android系统服务如电源管理、网络管理、位置服务等,都在源码中有...
在图像管理方面,ACDSee5.0.1具有强大的分类和搜索功能。用户可以创建自定义的文件夹、相册和类别,通过标签和元数据对图片进行整理。同时,其内置的智能搜索功能可以根据文件名、日期、甚至图像内容来快速定位到...
总的来说,74cms骑士人才系统v5.0.1正式版是一个功能完备、易于定制的人才招聘解决方案,适用于各类企业。通过其高效的执行、丰富的功能和灵活的设计,企业能够更好地管理和运营自己的招聘流程,吸引并留住优秀的...
VNC-5.0.1.rar VNC-5.0.1.rar VNC-5.0.1.rar VNC-5.0.1.rar
《PHPYun_v5.0.1 Beta版:云人才系统的深度解析》 PHPYun_v5.0.1.beta.0703,作为一款备受瞩目的云人才系统,旨在为求职者与雇主提供高效、便捷的人力资源管理解决方案。这款系统集成了多种功能,不仅能满足企业的...
【Net实战商用源码---最新TourEx旅游系统v5.0.1多城市版源码 旅游网源码.rar】这个压缩包文件包含了基于.Net技术开发的TourEx旅游系统的一个完整版本,主要用于构建多城市版的在线旅游服务平台。在深入探讨这个系统...
robotium-solo-3.4.1.jar,
源码中会包含网关的配置、初始化、数据包解析、传输以及与其他网络组件交互的代码。可能还包括错误处理和日志记录功能。 3. **多通道操作**:LoRaWAN允许网关同时监听多个频率,以提高网络容量。在V5.0.1中,源码...
《ACDSee 5.0.1:经典图像查看与管理工具详解》 ACDSee,作为一款全球广泛使用的图像查看和管理软件,其5.0.1版本因其丰富的功能和用户友好的界面,深受广大用户的喜爱。这款软件在早期的数字图像处理领域占据了...
首先,Spring框架的核心特性之一是依赖注入(Dependency Injection,DI),它使得组件间的依赖关系得以解耦,增强了代码的可测试性和可维护性。在Spring 5.0.1中,依赖注入机制更加成熟,开发者可以通过注解(@...