一 常见Android自动化测试框架及其应用
目前,Android基于UI层面的自动化测试工具,都可以理解为是基于Android控件层面的,涉及Widgets和WebView两大类。其主流的测试方法主要有以下几种:
一种是通过Android提供的各种服务,来获取当前窗口的视图信息。然后,在当前视图内查找目标控件,并根据该控件属性信息计算出该控件中心点的坐标,进而构造出一个Android Input事件来实现对应用的自动化测试。其主要特点是:测试代码和被测应用各自运行在各自的进程内,相互独立。其代表有Uiautomator。
另一种则是基于Instrumentation,通过把测试代码和应用代码,确切地说是测试APK和被测APK,运行在同一个进程中,通过Java反射机制,来获取当前窗口所有视图,并根据该视图查找到目标控件的属性信息,并计算出目标控件中心点坐标。然后,利用Instrument内部接口,实现点击操作。其代表有Robotium。
我们先来看下第一种。这类方法通常需要满足两个功能,一是能获取屏幕视图;二是能产生输入事件。这样,用户就可以通过屏幕视图查找到目标控件,进而计算出其中心点坐标,并由此产生一个输入事件来模拟用户操作。通常,这类框架还会提供一个截屏功能,方便用户对照。例如,分析定位问题等等。
目前,这类测试方法常见应用模式有以下几种:(1)、Hierachyview+monkey;(2)、uiautomator;(3)、accessibilityservice。(4)其他。先来说下第一种,Hierachyview+monkey的组合方式。
我们先来说下第一种,Hierachyview+monkey。其实现原理如下:
首先,hierahcyview通过socket与设备侧ViewServer建立连接,端口为4939。其次,通过命令“dump-1”获取控件属性信息。信息存入ViewNode中。第三,根据ViewNode信息,遍历控件树,查找到目标控件,并根据其bounds信息,计算出其中心点坐标。第四,根据计算出的坐标信息,发送一个点击该点的monkey命令给设备侧的monkey服务。除点击操作外,我们还可以通过Monkey服务进行输入、硬按键类操作。至此,对设备的一个自动化操作就完成了。这里需要说明的是,绝大部分商用手机ViewServer服务的开启都需要系统权限。故采用这种模式,手机一般需要root权限。另外,关于Hierachyview,CSDN上有一篇很好地介绍Hierachyview实现原理的文章,其连接地址如下:
http://www.cnblogs.com/vowei/archive/2012/08/08/2627614.html。现摘录其部分内容,关于从设备侧ViewServer获取控件层次结构图的过程,以便大家更好地理解该模式。
HierachyViewerDirector.java(即Controller)通过DeviceBridge.java来和Android设备通信,而DeviceBridge.java具体是通过AndroidDebugBridage.java和DeviceConnection.java来和设备通信。备注:Hierachyview本身采用MVC模式。
AndroidDebugBridge.java: AndroidDebugBridge.java是ADB API,位于ddmlib项目中。它实现了命令行版adb一样的功能,在HierarchyViewer中主要用到其连接设备,forward端口,启动ViewServer等操作。
DeviceConnection.java:负责和ViewServer通信,向ViewServer发送命令并接受其返回的信息。从而获取Activity列表、控件层次结构图、截图等。
第二种应用模式Uiautomator。UiAutomator是Google仿照微软Uiautomation提供的一套自动化框架,基于AndroidAccessilibilityService提供(注:Android AccessilibilityService,是一个可访问服务,是一个为增强用户界面并帮助残疾用户的应用程序,或者用户可能无法完全与设备的交互。例如,用户在开车。那么用户就有可能需要添加额外的或者替代的用户反馈方式)。其应用方式有以下几种,一种是UiAutomatorView+monkey,另一种是直接调用UiAutomator API。其中,第一种方法同hierachyview+monkey差不多。其区别是:UiAutomatorView通过ADB向设备侧发送一个dump命令,而不是建立一个socket,下载一个包含当前界面控件布局信息的xml文件。相比较hierachyview下载的内容而言,该文件小很多。因此,从效率上讲,这种方法比第一种应用模式快很多。第二种方法,则是直接调用UiAutomator框架对外提供的API,主要有UiDevice、UiSelector、UiObject等。其原理与第一种方式,即HierachyView+Monkey,差不多。其过程大致是:首先,UiAutomator测试框架通过Accessibilityservice,获取当前窗口的控件层次关系及属性信息,并查找到目标控件。若是点击事件,则计算出该控件的中心点坐标。其次,UiAutomator通过测试框架,注入用户事件(点击、输入类操作),从而实现模拟人的操作。UiAutomator对外提供UiAutomatorTestCase、UiDevice、UiSelector、UiObject、UiCollection、UiScrollable等类,其作用如下:
UiAutomatorTestCase:继承自Junit TestCase (Junit),对外提供setup、teardown等,以便初始化用例、清除环境等。
UiDevice:此类主要包含了获取设备状态信息,和模拟用户至于设备的操作两类API。UiSelector,主要是通过一定查询方式,定位到所要操作的UI元素。
UiObject:UiObject可代表页面的任意元素,它的各种属性定位通常通过UiSelector来完成。
UiCollection:UiCollection一般与UiSelector连用,如它的构造函数也要求提供Uiselector: UiCollection(UiSelector selector)。它的API较少,主要用以从Uiselector筛选出的元素集中挑出所要的元素:getChildByDescription(), getChildByInstance(), getChildByText() ,以及统计元素集的个数getChildCount()。
UiScrollable:UiScrollable用来表示可以滑动的界面元素,其继承关系为UiObject -> UiCollection ->UiScrollable。
但UiAutomator的实现方式与HierachyView+Monkey有很大不一样。以控件点击操作为例,其实现流程大致如下:
定义一个点击对象Object,该对象则通过UiSelector对象定位到具体的控件。而UiSelector则通过UiAutomatorBridge(它可看做是UiSelector与AccesibilityService之间的连接器),将查询内容(AccessibilityNodeInfo)和输入事件(AccessibilityEvent)传给AccessibilityService。实际业务过程比这复杂的多。这样,就实现了对某个控件的查找或点击操作。备注:AccessibilityEvent,所有可操纵的UI元素都定义为一个AccessibilityEeventt;AccessibilityNodeInfo指视窗中的组件树节点。
第三种则是accessibilityservice。先来介绍下Accessibilityserveice服务。前面已经讲过,它是一个Android的一个服务。若是用Accessibilityservice进行自动化,我们需要继承Accessibilityservice开发一个服务。这样,我们就可以依据这个服务获取当前界面的控件属性信息。其获取内容跟Uiautomator一样,都是AccessibilityNodeInfo。控件信息获取到后,若是要进行点击等操作,则可通过Monkey或其他方式,如Input等,来模拟点击操作。
上述几种Android测试方法中,UiAutomator比较正统,是Google正式推出的,也是应用范围最广的。另外几种方法,则见得不多,其中Hierachyview+monkey的方式,公司内部Ares就采用了。这类测试工具的一个好处就是可以跨应用。但不足之处也很多,速度慢、不支持WebView等(这种模式下,对WebView控制有限,无法注入Java Script)。
接下来说下第二种框架,即Instrumentation,它是Android对外提供的一系列的测试方法的核心。Instumentation可看成一系列控制函数的集合,作用于系统和应用之间,类似于Windows中的Hook。在该测试框架下,主程序和测试程序需要运行在同一个进程中,见下图(图片来源CSDN,链接地址:http://blog.csdn.net/jayfei0308/article/details/7950052)。
需要说明的是,在Android系统中,测试程序也是应用程序,我们可以将其看成一个没有UI的应用。
其实现过程大致如下:如图,InstrumentationTestRunner通过调用Instrumentation杀除应用程序的进程,再用Instrumentation重启该应用。这时,测试应用和被测应用就运行在同一进程下。测试应用怎么知道该测试哪个应用呢?嗯,这是通过在测试工程的mainfest文件中添加元素来实现的。当测试应用和被测应用运行在同一个进程里,它们之间就可以通过Instrumentation来进行消息交互,从而达到测试效果。当Instrumentation与某个程序交互时,其大致采用如下步骤:(资料来源:
http://blog.csdn.net/fireworkburn/article/details/20144153)。
首先,启动时,初始化测试APK的配置文件AndroidManifest.xml文件中。该配置文件中标明了所使用的测试运行类、被测目标应用、包名等。然后,启动被测应用的Activity。同时,将测试ActivityThread做为一个引用进行初始化。此时,如果找不到目标应用则会报错。其次,执行测试脚本。测试时,测试工程中任何对目标应用进行的操作,都会用异步的方式,将消息体放在目标程序的MessageQueue中。这样,目标程序在查看到自己的MessageQueue中有内容时就会执行。
基于Android Instrumentiaon开发的测试工具有很多,其中最有名的恐怕要数Robotium了。目前,网络上很多移动应用测试平台,如百度移动应用测试平台MTC,都支持Robotium。
二 各类Android测试工具的TestCase继承关系
Android提供了很多测试工具,如Monkey、Instrumentation、UiAutomator。其中,基于Android测试工具进行二次开发的测试工具也很多,如Robotium、Espresso。它们的继承关系下图:
UiAutomator Testcase类继承自JUnit的TestCase类。而Robotium、Espresso则继承自activityInstrumentationTestCase2。从这个继承关系,我们也能理解为什么采用Robotium的方式,应用需要签名。而采用UiAutomator则不需要。其原因是:采用Robotium的方式,其测试代码本质上是一个APK。根据Android的安全机制,应用是需要签名的。
三常见Android自动化框架优缺点关系
这里主要介绍下前面讲的几种测试工具的优缺点,包括HierachyView+Monkey、UiAutomator、Robotium。
| Hierachyview+Monkey | UiAutomator + Monkey | Robotium |
权限 | root | 普通 | 普通 |
是否需要签名 | 是 | 否 | 否 |
响应速度 | 10s(网友测试数据) | 4s(网友测试数据) | 1-2s |
是否支持WebView | 否 | 否 | 是 |
是否支持跨应用测试 | 是 | 是 | 否 |
支持该特性的Android API | ? | API 16 | API 7 |
是否支持控件ID | 是 | 否 | 是 |
从上述数据来看,Android提供的测试工具各有优缺点,有的支持WebView测试,有的不支持。有的支持跨应用,有的不支持。因此,一个好的Android测试工具,更多地是兼容了上述几种测试方法。例如,Appium。
转自:http://bbs.c114.net/blog-1025779-5322.html