在版本快速迭代抢占市场先机的同时,更需要严苛保证 APP 产品质量,确保客户资金及交易安全。本文介绍了金科公司智能移动应用测试云平台(IMC)自动化测试模块的系统架构、技术实现和实施经验。期望在提高项目组测试效能,优化测试资源配置、完善企业级质控体系等方面起到积极作用。
APP 自动化测试的特点及实施原则
APP 自动化测试,就是按照业务需求编制自动化脚本,通过测试框架在移动终端上批量调度执行,自动完成对 APP 的测试工作。自动化测试具有以下优势:
执行效率高。 测试任务可以在任意时间下启动,无人值守执行速度较快。执行过程中可同步采集系统日志及截图,自动生成测试报告。
节省测试资源。 一方面减少进行重复性劳动的人力成本,另一方面通过对测试终端的分时复用减少硬件投入。
克服手工测试的不足。 可以进行大规模、长时间的测试,并且严格保证每次测试执行的一致性,避免人为松懈与出错。当然,自动化测试也有很多局限性,比如需要持续开发和维护自动化脚本、无法进行探索式测试等,短期内是无法完全代替手工测试的。
根据以上特点,结合项目经验,总结出实施原则如下:
选择具备敏捷特性的开发项目。 将自动化测试纳入持续集成流水线,实现自动触发及闭环反馈,才能在足够多轮次的敏捷迭代中获得收益。
应用在冒烟及回归测试阶段。 在冒烟测试阶段,自动排查代码误提交、构建错误、测试环境未就绪等问题,避免浪费测试人员的时间和精力。在回归测试阶段,无人值守自动完成完整的大规模功能回归验证。
挑选核心且稳定的业务。 以建行手机银行例,挑选功能稳定的核心动账交易纳入自动化的实施范围。如大小额转账、信用卡还款、贷款支用等,称之为重要未变动功能。这些业务功能覆盖了 APP 的主要菜单,确保 APP 核心功能正确。
自动化测试在实施时主要考虑作为手工测试的补充,将测试人员从复杂繁琐的回归测试中解放出来,重点关注新上线功能,其余的质控工作交由自动化系统保障。人机结合使项目的投入产出比达到最优,增强投产信心,实现 APP 测试的整体效果及对质量的持续监控。
测试平台发展历程及系统架构
APP 自动化测试 1.0 时代,基于开源 Robot framework 和 AppiumLibrary 搭建本地化部署的 C/S 架构的移动金融 APP 自动化测试工具。基于关键字模式,实现脚本的模块化封装和积木式编排,提高复用性及易用性。但经过几个项目试点应用,发现推广起来十分不易:
一是需要单独开发和维护一套客户端版本;
二是受行内安全策略影响,本地电脑 USB 口被封禁,无法在云桌面或本地通过 ADB 工具连接手机。
APP 自动化测试 2.0 时代,封装了多种移动端测试工具链的智能移动应用测试云平台 IMC 投产上线,通过 B/S 架构为各事业群移动项目组提供 APP 测试服务,开启了云端测试模式。普通手工测试工程师、分行业务人员均可通过远程的方式,轻松在线租用真实手机终端,完成 APP 自动化测试。
两个平台都无例外包含以下几个模块:
控件识别模块。 适应复杂场景,适配 Android 及 iOS 最新平台,支持 H5 、原生、混合 APP 架构。封装控件识别插件,支持基于控件属性、图像、字符识别等方式。
自动化脚本录制模块。 降低自动化录制门槛,实现相同流程下,一套自动化脚本可以在多平台上执行的能力,大大降低了脚本编写及后期维护成本。
持续集成模块。 将创建任务、任务状态、测试报告接口暴露出来,通过持续集成框架进行调度,实现与 APP 项目敏捷研发流程的对接,形成敏捷测试流水线。
测试数据供给模块。 统一整合客户信息、存款借记卡、贷记卡等业务数据库,实现测试数据的企业级集中供给。支持数据库、表达式、接口等多种方式批量获取测试数据。
脚本及数据管理模块。 脚本同步上传云端,实现企业级的自动化脚本库及版本管理。同时完成对合约关系、卡账客状态等交易要素的批量预埋动作,确保数据状态满足自动化运行要求。
执行调度模块。 实现大规模自动化执行。支持全天候、队列式、分布式稳定调度执行,支持设备的分时复用。
测试结果分析模块。 全程记录测试过程日志,汇总执行结果。对失败案例步骤进行截图,整合形成测试报告。
移动金融 APP 自动化测试关键技术
相对于一般影音娱乐类、资讯阅读类等 APP ,移动金融类 APP 业务功能多、范围广,具有交易流程关联性强、交易场景复杂的特点。
为了实现移动金融 APP 自动化测试的规模化、专业化和智能化,需要平台能够支持高效的流程编排、智能的页面元素识别控制、稳定的测试全流程异常监控、大规模的金融业务案例分层复用以及专业的持续集成。为此我们针对性的研究了以下关键技术。
脚本及流程编排技术
基于关键字驱动模式
基于关键字驱动的模式设计测试脚本,需要关键字设计得通俗易懂,以便于理解和编排。引入 Robotframework 及 AppiumLibrary 封装的关键字,涵盖基本的 APP 操作。结合关键字及参数,即可实现对 APP 的各类操作。
常用的典型关键字如表 1 所示。
系统类关键字主要包括安装、调起、关闭、卸载、截屏等系统功能,实现 APP 测试环境的准备;
操作类关键字主要包括点击、输入、滑动,记录测试步骤实现流程编排;
断言类关键字包括检查元素是否存在、文本是否符合预期等,实现对测试结果的验证。
此外根据测试特定需要,编制自定义类用户关键字。比如返回首页功能,实现每条案例测试完毕后回到首页,统一脚本执行起点实现案例间解耦。获取短信验证码功能,实现从后台短信服务器获取指定测试环境、指定测试手机号码的验证码。不断完善的关键字及字典,使脚本更加灵活与强大。
基于操作录制回放模式
为了提升自动化测试成本,提升测试效率,IMC 平台对底层实现技术进行了进一步封装和优化。提供了几乎没有学习成本的录制 - 回访模式。用户的操作会被记录下来并自动生成测试脚本,支持在其他设备上进行重复回放、批量回放等功能。
技术实现上:
对于 Native 控件,通过 AccessibilityService 监听用户操作事件并获取对应的控件信息;
对于 H5 控件,通过 ChromeDevtoolProtocal 与 Chrome 内核通信,注入 JS 进而获取到 HTML5 的完整页面结构信息从而获取到页面结构。
多方式精准控件识别
自动化脚本需要能对 APP 界面上的文本框、输入框、密码框、按钮、下拉框、多选框、日期等各类控件对象进行捕获、定位进而控制。所以控件识别的准确性是决定自动化成功率的关键因素。为此研究控件精准识别三板斧,分别是基于控件属性、基于图像识别和基于字符识别。
基于控件属性识别
通过对 AndroidSDK 中的 uiautomatorviewer 工具进行二次开发,将页面控件元素可供定位的属性清晰地展现给自动化脚本编写人员,包括 ID、Text、Class、XPath、Position 等,如图 3 所示。常用的定位属性及使用样例见表 2。对于 90% 以上的页面控件,通过控件属性即可进行识别和控制。
控件属性 | 样例 |
---|---|
identifier | Click Element / identifier=identifier_element |
resource-id | Click Element / id=id_element |
name | Click Element / name=name_element |
class | Click Element / className=UIAPickerWheel |
xpath | Click Element / xpath=//UIADiv/UIAButton |
accessibility_id | Click Element / accessibility_id=button2 |
基于图像识别
在实际编写自动化测试脚本时,仍然会遇到许多基于控件属性方法失效的情况。比如控件属性没有赋值、需要操作的元素非原生控件、控件属性随机变化无法定位、安全要求不允许捕获控件等。比较典型的场景为安全密码键盘。以建行手机银行为例,登录及支付时会弹出定制化的安全键盘,此控件不允许捕获,不允许直接传入密码文本。只有实际点击屏幕上对应密码按键才能校验通过。
对此研究基于图像识别的解决方案,通过引入 OpenCV 开源计算机视觉库,基于 Python 开发 RF 关键字,通过在目标图像中寻找匹配模板,实现对密码键盘上每个按键的图像识别和坐标定位,如图 4 所示。
调用 OpenCV 的 matchTemplate 函数在图像模板和输入图像之间寻找匹配,获得匹配结果图像部位的起始坐标,结合输入图像的长宽值进行坐标转换后,输出匹配部分中心位置坐标。核心代码及实验结果如下所示。Get_keyboard_number_location 函数传入参数为测试环境初始密码 ccb123456 ,输出结果为识别耗时及定位坐标。可见系统准确识别出了每个字符对应的坐标,点击动作精准,安全校验通过,如图 5 所示。
1.def get_keyboard_number_location(im, pwd): 2. numbers =set(list(pwd)) 3. templates ={} 4. positions ={} 5.for i in numbers: 6. templates[i]= os.path.join("n{}.jpg".format(i)) 7. start = time.time() 8. img_rgb = cv2.imread(im) 9.for teNum, tepath in templates.items(): 10.template= cv2.imread(tepath) 11. height, width =template.shape[:-1] 12. res = cv2.matchTemplate(img_rgb,template, cv2.TM_CCOEFF_NORMED) 13. threshold =.95# 匹配算法阈值参数,数值越高则匹配精度越高,1 为完全匹配 14. loc = np.where(res >= threshold) 15.if len(loc)>0: 16. positions[teNum]= zip(*loc[::-1])[0] 17.else: 18.print("Can not found number: [{}] in image: [{}].".format(tepath, im)) 19.end= time.time() 20.print(end- start) 21.return[positions[n]for n in pwd] 22.if __name__ =="__main__": 23. ls = get_keyboard_number_location('./main.png','ccb123456') 24.print(ls)
基于字符识别
金融类 APP 为了防止恶意程序批量发起作弊交易,会设计乱序键盘、图片验证码等场景,或将重要交易要素转化为非字符的图片,防止爬虫截获,保障金融信息安全。此外,还有基于用户行为及交易数据推荐金融产品,设计的可灵活动态生成的功能区。比如在建行手机银行 APP 中,首页自定义快速链接,可自由配置 43 种金融产品。客户财富中心中的 e 账户开户交易、安全中心中快捷支付解绑等交易,增加了校验图片验证码环节。
这些场景,基于前两种识别方式,是比较复杂繁琐或根本无法实现的。对此,我们研究了基于光学字符识别(Optical Character Recognition,简称 OCR)的解决方案,通过引入开源的 Tesseract-OCR 引擎,从图片中识别字符,将识别结果回填到交易栏位继续提交,或进行测试结果判断。官方提供了中文识别训练文件 chi_sim.trainedata。要想获得更高的识别率,需要自行训练样本。目前也有腾讯优图、百度云等提供在线 OCR 服务,提供开放 API 供开发者使用。
中断及异常处理技术
在测试金融 APP 过程中,借记卡转账、贷记卡还款、理财基金申购等动账交易一般会触发短信验证码校验。再比如提交特定的交易要素时,会弹出提示框要求客户确认。此外还有一些随机出现的升级广告弹窗、网络不佳情况下的提示框、位置切换时系统提示框等。
这些都是影响自动化测试按预期步骤执行的中断及异常。对于短信验证码中断,开发获取验证码的 RF 关键字,用于从测试环境短信服务器数据库读取验证码短信内容,对其进行正则解析和截取后,将验证码回填到指定交易栏位。
对于异常弹框,修改 Appium 中的 Bootstrap 模块,使用 uiautomator 中的监听器实现测试全过程监听指定的异常弹窗。具体实现为,在 UiWatchers.java 中注册异常弹窗监控类,用异常弹窗的界面特定标识创建 UiObject 对象,当对象存在时进行点击处理,在 listenForever 方法中进行调用,即可实现对异常弹窗的长监听。核心代码及检测结果如下。丰富的中断及异常处理机制保证自动化执行的稳定可靠。
1.publicvoid registerPopupWatcher(){ 2.UiDevice.getInstance().registerWatcher("myPopup",newUiWatcher(){ 3.@Override 4.publicboolean checkForCondition(){ 5.// 监听建行手机银行 WIFI 连接断开弹窗 6.UiObject wifiPop =newUiObject(newUiSelector().textContains(" 网络连接已断开 ")); 7.if(wifiPop.exists()){ 8.System.out.println("you have a WIFI-unstable popup window"); 9.try{ 10.UiObject wifiPop1 =newUiObject(newUiSelector().resourceId("com.chinamworld.main:id/dlg_right_tv")); 11. wifiPop1.clickAndWaitForNewWindow(); 12.returntrue; 13.}catch(UiObjectNotFoundException e){ 14.Log.e(LOG_TAG,"Exception", e); 15.} 16.} 17.returnfalse; 18.} 19.}); 20.Log.i(LOG_TAG,"Registered WIFI-unstable Popup Watchers"); 21.}
案例模块化分层
案例分层的思想,即把案例的实现过程进行抽象和封装,分层编排及复用,从而提高灵活性、扩展性、可复用性和易维护性。
结合金融业务场景,设计三层关键字分解模型如图 7。核心思想是将对页面的原子操作封装成交互层用户关键字,然后在业务流程层关键字中进行调用,进一步封装成功能相对独立的业务功能单元,接着通过对业务流程层关键字的编排组合,实现一条测试用例。
分解模型越靠近上层,脚本越接近自然语言,甚至可以手工测试用例为基础进行快速开发。越靠近下层,脚本越接近实现代码,后续若界面更新变化,只需在很少的地方调整。即便测试的流程发生变化,也可方便的在流程层中调整。
持续集成
以目前主流的持续集成工具 Jenkins 为例,与智慧协同平台版本计划基线、版本机打包流水线对接,按项目需求配置构建触发器参数后,可实现在 APP 打包后,触发自动化测试任务。自动将安装包从制品仓推送到 IMC 平台的移动终端进行安装,然后执行相应的冒烟和回归测试,测试完成后推送分析结果到指定位置并发送通知邮件。IMC 平台完成本次测试任务的运行统计、日志搜集、报告归档等工作。测试人员只需要维护自动化脚本,即可实现无人值守的自动化测试工作。