众所周知,自动化测试可以一定程度上减轻测试人员负担,提高测试效率,并且通过自动化还可以实现可靠性测试和性能测试。对于移动客户端测试而言,如果我们能够让手机自动运行应用程序来帮助我们检测功能的正确性,会不会很酷?有道测试组对一些热门的手机自动化工具进行了调研,并选择了一些工具进行实际的使用。本文将会结合实际工作,对移动客户端(Android&iOS)GUI自动化的工具调研和实现进行介绍。
Android APIs [1] 提供的instrumentation类可以初始化Android应用程序代码,允许你监控应用程序的系统交互,配合KeyEvent、MotionEvent类,发送用户事件,进而实现GUI 层的自动化。测试程序需要继承ActivityInstrumentationTestCase2来实现自动化。
为了方便编写自动化测试用例,我们需要对ActivityInstrumentationTestCase2进行扩展。业界也已经有一些成熟的自动化工具,诸如Robotium、Athrun、NativeDriver、MonkeyRunner等。我们需要针对自身产品的需求,从中选取一款合适的工具来实现自动化。对于移动客户端GUI的自动化而言,需要保证选取的工具有以下几点特性:
表1列出了这四款工具的区别:
Robotium | Athrun | NativeDriver | MonkeyRunner | |
脚本语言 | Java | Java | Java | Python |
易扩展 | ● | ● | ● | ● |
易维护 | ● | ● | ● | ○ |
满足需求 | ○ | ● | ● | ○ |
易校验 | ● | ● | ● | ○ |
可持续集成 | ● | ● | ● | ○ |
表1 Android自动化工具对比
MonkeyRunner通过编写Python脚本来实现自动化,结果的验证是通过截屏比对图片来实现,验证方式不够灵活,不建议采用。
NativeDriver [2] 是WebDriver 接口的一种实现,使用移动客户端原生UI而不是浏览器UI(Selenium)的自动化测试工具。类似于selenium RC的方式来运行测试程序,对于熟悉WebDriver的用户,上手会很快。从表1可以看出该工具也可以满足我们的自动化需求,但在调研初期,该工具提供的接口较少,没法满足测试需求,而今的完善程度也已经很高了。没有使用该工具可以认为是历史原因吧。
Robotium [3] 被大家所熟知,基于instrumentation实现,提供的接口可以满足大部分自动化需求。但不支持webview,而有道词典的查词结果展示恰好使用的是webview组件,该模块就没有办法通过该工具来实现自动化。
Athrun [4] 的实现和Robotium类似,提供的接口也很多,并且支持webview,也可实现持续集成。对于我们的产品而言,满足自动化的需求。由于工具开源,在今后需求不满足的时候我们也可以在该工具的基础上做一些封装。所以最终选择了Athrun来实现笔记和词典的GUI自动化。
和写Android应用类似,首先要建立一个Android Test Project ,指定被测试的Android Project。如果没有应用源代码,也可以在测试程序的AndroidManifest.xml文件内,修改<instrumentation> 标签下targetPackage为我们要测试的应用程序的package。之后导入framework.jar,就可以开始编写自动化脚本了。图1是有道云笔记Android端登录模块的自动化用例:
图1 Android 自动化用例
我们需要继承AthrunTestCase,指定package和想要开始的Activity 。每一个方法作为一个测试用例,最后以Android JUnit Test的方式运行测试用例。这里需要注意的一点,要先在设备上安装被测试的应用。如果这个应用是签名过的,那么我们的测试应用也需要用一样的签名。
从代码可以看出,寻找组件的接口很简单,可以通过组件的id、value等属性来寻找。如果组件没有相对独立的属性,也可以通过该组件的父节点一层层来寻找。Android SDK提供的hierarchyviewer工具将模拟器当前Activity的 UI组件以树状形式展现,可以清晰的看到每个组件的详细属性。
验证一条测试用例是否通过的方式也有很多种,可以验证Activity的跳转、组件的展示,当然还有一些可能就需要通过截屏。图1是通过验证执行用例后Activity的跳转来判断测试用例是否通过。
以上我们就完成了一条测试用例的自动化。显然基于Athrun的框架,使得我们的自动化用例编写方便了很多,成本也大大降低了。
为了完成各种自动化测试用例,我们有必要对Athrun有更详细的了解,以便二次开发所需接口。感兴趣的朋友可以通过 http://code.taobao.org/svn/athrun/trunk/android/ 来下载工具源代码。
在介绍iOS自动化之前,首先要介绍下Xcode 所提供的 instruments [5] 工具。该工具是一款用来动态跟踪和分析OS X和iOS代码的实用工具。这是一个灵活而强大的工具,它让你可以跟踪一个或多个进程,并检查收集的数据。这样,Instruments可以帮你更好的理解应用程序和操作系统的行为。
instruments除了提供自动化工具automation外,还有诸如leaks、allocations等用来检测和分析程序性能的工具。对于iOS测试和开发而言,追踪和定位缺陷,instruments是非常实用的。图2是instruments的主界面:
图2 instruments 主界面
关于instruments所提供的各种工具的使用,感兴趣的朋友可以在 iOS Developer Library 中了解。
接下来就要介绍一下UI Automation,它可以用在真实设备或模拟器来执行自动化测试。
使用JavaScript编写测试用例,调用UI Automation的接口模拟用户交互操作。该工具会将自动化运行的日志信息返回到instruments 信息栏。
在Xcode通过 profile的方式来启动instruments。或者直接双击启动instruments,在instruments主界面中选择设备上被测试的应用程序。然后在Automation Script栏编写自动化脚本。使用iOS设备需要注意的一点是确保Developer profile设置是Release模式。图3是有道云笔记iPhone版登录模块的自动化用例:
图3 iOS 自动化用例
完成自动化脚本后,可以通过点击Instruments 的Record按钮来运行,也可以通过instruments相关命令来运行。前者适合于调试,后者适合于持续集成。
从图3可以看出,对应的UI 组件需要逐层指定。定位这些组件有两种方式。对于iOS 5以上的系统可以通过录制生成脚本,但录制的方式可能会记录错误。所以为了定位准确的组件位置,就需要调用logElementTree ,将当前屏幕组件的层次树状结构打印到日志中,通过日志定位组件。
从上图也可以看出UI Automation 所提供的验证机制有些繁琐,验证每一个组件是否存在都需要去做判断。这仅仅是冰山一角,UI Automation会对捕获到弹出窗口(alert)点击默认操作按钮,提供的日志文件也不便于分析,所以我们有必要对UI Automation的接口进行二次封装,更方便去编写自动化用例。
Athrun也提供了iOS的自动化框架,有三种实现方式。第一种AppFramWork是代码注入型,需要在源码中插入测试代码,Objective-C编写测试用例,自动化成本较高,不建议使用。第二种instrument Athrun就是对UI Automation的接口进行扩展,提高了原有接口运行的稳定性。第三种instrumentDriver基于instrument JS框架来开发InstrumentDriver服务端,在java上实现客户端,使用java脚本控制iOS自动化执行。该框架还实现了单步运行,调试等UI Automation没有的功能。图4为instrumentDriver的架构图:
图4 instrumentDriver 架构图
从instrumentDriver的介绍可以看出,相比苹果所提供的UI Automation是有不少优点的。目前由于我们需要通过自动化脚本配合instruments 其他性能检测工具来实现对应用程序的性能测试,所以依旧采用instruments 原生工具配合扩展的JS脚本的方式。后续如果可以找到更好的获取性能数据的办法,会逐渐转向instrumentDriver的方式来实现iOS的自动化。
从表2可以简单看一下目前我们选择的iOS和Android自动化工具的区别:
脚本语言 | 测试单个页面 | UI组件定位 | 测试结果 | |
iOS | JavaScript | 不支持,从启动的view开始自动化 | 录制logElementTree | 不便于jenkins [6] 展示,需转化格式 |
Android | Java | 继承时指定对应的Activity即可 | hierarchviewer | JUnit运行结果,方便jenkins展示 |
表2 iOS和Android自动化工具对比
自动化的实现一定程度上提升了我们的测试效率,由于互联网产品迭代速度较快,这里建议大家自动化从冒烟测试做起,用例设计要尽可能简洁,多做封装,以便降低维护成本。同时实现自动化的持续集成,更早介入测试,更早发现问题。在此基础之上,我们还可以通过自动化配合获取性能数据的脚本来实现对应用程序的性能测试。这些工作可以使得我们的测试覆盖更广,测试力度更深,更好的检测和监控产品质量。
[1] Android APIs https://developer.android.com/guide/components/index.html
[2] NativeDriver http://code.google.com/p/nativedriver/
[3] Robotium http://code.google.com/p/robotium/
[4] Athrun http://code.taobao.org/p/athrun/wiki/index/
[5] iOS library http://developer.apple.com/library/ios/navigation/
[6] Jenkins http://jenkins-ci.org/
[7] from http://techblog.youdao.com/?p=571