cover_image

RPA在IM资源位验证场景中的应用

张慧吉 之家技术
2022年06月21日 10:00

关注“之家技术”,获取更多技术干货

图片
总篇147篇 2022年第22篇

★ 目录 ★

01

项目背景

02

预期目标

03

技术选型

04

系统设计

  4.1 如何保证脚本运行稳定性

  4.2 自启动程序

  4.3 脚本动态下发

  4.4 运行记录管理

  4.5 入口监测

  4.6 JSON对比模块和图片对比

  4.7 变更入口标注

05

实现效果和收益

06

后续规划


1

项目背景


IM即时沟通工具挖掘不愿意留资电话的用户,通过在线答疑、预约试驾等服务触达潜客;通过汽车之家站内资源与站外资源的拓展,站内如汽车之家App、汽车报价App等,站外如高德、微信、百度、支付宝小程序等,实现多种入口的流量汇集。不同的入口设置不同的文案和样式,流量获取转化率也不一样。如此众多的流量入口和多样化的样式,就算产品老司机也很难一口气全部说得完整,更何况随着产品运营人员流动,入口的控制更是难以全面掌握。那么众多入口每天是否正常漏出,或者运营后台调整文案和图片后,各入口是否显示正常呢?由于人工遍历上百个功能入口需要花费大量的时间,产品运营同学很难去一一验证。如何合理有效地保证各处流量入口显示正常和及时发现异常是一个亟需解决的问题。在深度分析IM众多入口形态后,笔者基于移动端RPA积累的经验,设计了IM入口巡检工具,每小时对IM的各处流量入口进行自动遍历,通过检测控件判断入口是否显示正常,通过智能分析界面元素差异判断入口样式变更,并自动生成入口截图,便于产品运营同学确认。既能保证IM入口显示正常,也能最大程度上减轻产品运营同学验证的成本。


2

预期目标


IM入口巡检工具旨在模拟人类和系统交互的动作,从而执行入口显示检测和样式变更,具体包括如下几点。
*预期实现功能分为两类:一种是检测IM各入口是否显示,另一种是检测某些功能IM入口的样式是否变更;
*每小时对IM各入口进行定时监测截图;
*自动监测未正常显示的入口和样式变更的入口,将结果及自动生成的截图推送给产品运营及时确认;
*无人值守自动稳定运行。


3

技术选型


在移动端自动化建设过程中,我们先后对Appium、Macaca、Airtest、AutoJs等工具进行了预研和试用。其中Appium、Macaca、Airtest均为Client/Server架构,需要安装在电脑上,手机连接到电脑上后,通过程序发送命令,服务器端接收命令,驱动移动设备上执行命令并且把执行的结果返回给程序。虽然均支持Android/IOS跨平台自动化,但是依赖相对复杂,自动化依赖的电脑很难部署到生产环境中,测试环境的不稳定性,在进行自动化测试时尚可接收,对于服务于产品人员的业务,部署在测试环境,很难保证质量稳定。

AutoJs主要原理是基于Android的无障碍辅助服务 AccessibilityService,通过Rhino引擎是实现JavaScript编写脚本。无障碍服务设计初衷是用来帮助残障人士使用Android设备和应用的,不过开发者发现其强大的可操作性,将其发扬光大,演变出来了一系列自动化脚本工具,AutoJs就是其中成功之一。无需连接电脑,在手机端就可以独立运行,甚至可以在手机上直接编程。便于实现去中心化的架构,相比于Appium、Macaca、Airtest必须依赖于Server更灵活,更便于扩展设备规模。

上述四个工具均是开源工具,我们均可以针对个性化的需求进行二次开发。Appium和AutoJs社区相对活跃,遗憾的是不少灰产都用AutoJs来薅羊毛,从V4.1.1以上作者更改为收费版。好在我们可以基于V4.1.1的开源版本进行维护和扩展,本着科技向善的初衷我们使用AutoJs在提升工作效率方面进行了应用。


4

系统设计


IM入口巡检借助AutoJs实现编写脚本和自动化操作App,通过服务端动态下发机制实现脚本的热更新,通过对界面控件的遍历和截屏实现界面镜像,基于本次和上次运行控件JSON结构的对比和图片对比实现IM入口样式的监测和差异内容标注,对比完成后自动生成IM入口巡检报告发送给相应的产品人员,便于及时关注和确认,具体设计如下。

图片

图1 IM入口巡检工具模块图


4.1如何保证脚本运行稳定性 

【脚本粒度拆分】

当需要针对多个App,进行多种业务流程的脚本编写时,为了保证各流程稳定运行和失败可独立重试,如何拆分业务流程显得格外重要,大致总结原则如下:

A.不同App的脚本拆分,保证一个脚本中关联的packageName唯一;

B.无关联的业务流程脚本拆分

C.同一个脚本中的各个模块独立可重试,每个独立模块尽量从首页开始,比如监测首页-选车频道-品牌列表-车系列表有没有直播入口,以及首页-搜索车系-搜索结果页有没有直播间入口,两个模块没有依赖关系,尽量封装成独立的模块,起始路径均从首页开始,不要相互依赖。一旦其中一个模块由于异常运行失败,不会影响其他模块的正常运行。

D.共用模块的封装,对于查找控件超时、根据父节点获取JSON结构、点击控件中心区域、滑动指定距离、截屏等通用操作封装为公用函数。

【控件查找】

一般而言在自动化测试查找控件时尽量使用resourceId来确定,因为其相对固定。笔者在初期版本中也是这么使用的,屡试不爽。然而随着App对资源进行混淆后,资源名发生变化,每次发版生成的resourceId均会发生变化,如果继续使用resourceId查找控件,会导致找不到资源id。万幸的是,凡事总有解决办法,这里总结一些查找控件的技巧。

·自动化脚本尽量基于控件操作,不要基于坐标操作,坐标是不靠谱的,先不说不同设备坐标不一样,即便同一个设备也会因为界面上的一些动态元素而变化。

·其中有个例外,控件点击尽量不要使用控件的click函数,由于Android只有控件的clickable=true时才能响应点击事件,而该属性可能在某个控件上开启,也可能在其父布局,甚至祖父布局才可以响应点击,不确定性非常大。为了运行稳定,当根据属性值查找到控件后,无需关心其clickable属性是否为true,动态计算该控件的中心点坐标,直接调用坐标点击事件响应更稳定。

·根据非唯一性属性查找控件时(如className或text),尽量附加区域属性,及在某个区域里查找,能更稳定运行。如下所示,通过多个属性唯一确定控件。

packageName(packagename).className("android.widget.EditText").boundsInside(0, 0, device.width, device.height / 7).clickable(true)

      ·对于只能通过文本查找控件是,建议使用正则表达式匹配,这样可以根据一组文本进行查找,即便对于动态变化的文本,只要命中其中之一就可以正常运行。

packageName(packagename).className("android.widget.TextView").boundsInside(0, 0, device.width, device.height).textMatches("/同城直播|同省直播|直播选车|有问必答|直播买车/")

【App自动升级】

由于IM投放的各个App会按周期发布新版本,所以及时平滑地升级App是先决条件。最容易想到的入手点就是应用内检测更新,然而近年来手机厂商出于安全原因会对非应用市场来源的安装包进行拦截,导致安装步骤非常繁琐,有的手机甚至要输入安装密码。换个思路,那我们把应用商店当作一个App,在应用商店里搜索指定App,检测并安装升级,这样脚本更通用稳定,每日在运行所有任务前先执行汽车之家App和汽车报价App的升级更新操作,保证针对最新的版本进行监测。


 4.2自启动程序 
为了保证手机电池尽量延长寿命,我们会设置手机每日关机一段时间。在每日手机重新开机后如何启动IM入口巡检脚本是个需要解决的问题。这里可以利用到Android系统的开机广播,我们通过创建自定义广播实现对android.intent.action.BOOT_COMPLETED广播的监听。可以编写独立的App实现该功能,然后再唤起AutoJs,也可以直接修改AutoJs源码,笔者倾向于前一种方案,更便于维护。

4.3脚本动态下发 

由于App运行环境复杂性和App本身多变性,IM入口巡检工具不可避免的要有一定的升级工作。基于AutoJs的脚本以打包成独立App的形式运行,完全独立的运行在手机端。通过重新打包App、重新安装的方式升级工具也未尝不可,但是毕竟步骤比较繁琐,时间成本高,如果脚本能够动态下发、动态生效更能简化维护工作。

经过研究发现AutoJs支持通过engines.execScriptFile(‘本地脚本路径’)的方式加载运行脚本,这就为动态执行脚本提供了可能性。在云端通过脚本管理功能对不同的脚本进行维护,并赋予版本号的概念。移动端通过API获取最新脚本信息,对比本地脚本的版本号和云端版本号,如果本地版本号较低,则通过文件下载的方式,将云端脚本下载到本地,覆盖本地脚本,并将本地版本号设置为最新,这样在后续运行中使用的就是最新脚本。动态脚本下发将大大简化后续脚本维护的工作量,让IM入口巡检脚本的适配工作更及时。


4.4运行记录管理 

IM入口巡检工具目前主要针对入口是否正常漏出和页面样式是否变化两类进行监测,两类监测在上报运行记录方法各有侧重点。入口样式监测重在监测入口是否正常显示、入口样式是否有变化,会采集是否查找到目标控件、控件左上角坐标、右下角坐标、屏幕截图等信息上报到服务器端。其中入口样式的变化基于截取控件矩形区域内的图片进行对比得出。

页面样式监测的原理是根据入口布局的根节点,递归遍历所有子节点,将所有叶子节点(没有孩子节点)的控件加入到集合中,组合成JSON格式上报,其中对于每个叶子节点采集text、resourceId、className、desc、posX、posY、left、top、right、bottom等属性,用于对比差异。页面改版内容最终上报的信息包括页面唯一标识、App版本号、叶子节点数量、JSON结构文件、截图。


 4.5入口监测 
云端接收到入口样式监测记录后,相较于上次运行,入口是否正常显示,如果本次运行未显示,则直接报警。如果本次运行正常显示,则只截图。

4.6JSON对比模块和图片对比 

入口样式监测是通过两种方式对比得出结果,一是对比本次和上次运行IM入口布局中叶子节点构成的JSON结构得出入口样式元素的变化;另一方面是通过对比IM入口布局图片的差异,得出颜色和图标变化。

JSON结构对比:如果App版本号发生变化,则说明App有新的升级包,App中的所有resourceId均会变化,直接提醒产品人员有升级,不再触发后续逻辑。如果版本号没有变化,对于每个页面唯一标识,如果叶子节点数量相等,则认为页面没有变化,反之则会对比本次和上次运行的JSON结构,JSON结构中每个叶子节点采集text、resourceId、className、desc、posX、posY、left、top、right、bottom等属性,遍历本次JSON结构中的节点,如果本次相对于上次运行有新增或减少的resourceId、或者resourceId的文本发生变化即认为该入口发生变更。

图片对比:使用OpenCV截取IM入口布局左上角坐标、右下角坐标区域内的图片,将本次和上次运行入口区域图片进行对比得出结果。图片对比基于OpenCV实现图像模板匹配算法,将期望素材与备选截图进行对比,由于patch尺寸可能不同,需要进行滑动匹配窗口,扫描整幅备选截图获得最好的匹配patch。预期监测的所有入口均执行完成后,根据JSON结构对比和图片对比即可得出入口样式是否变化的结论,附加到IM入口巡检报告中。报告中只显示未正常漏出的IM入口和样式变更IM入口,产品运营同学只需要关注异常及变化即可,无需每次都关注上百个IM入口。


4.7变更入口标注 
基于上述步骤计算出本次相较于上运行次的变更的入口集合后,为了产品人员更直观的查看差异,我们使用ImageIO类库将本次和上次的截图合并到一张图片中,并在本次运行截图中将IM入口通过红色方框标注出来,差异一目了然。图片

图 2 IM入口样式差异对比


5

实现效果和收益


IM入口巡检工具实现了无人值守情况下,每日针对汽车之家App和汽车报价App中各处IM入口监测和样式变更自动遍历和分析,自动计算出变更信息,及时通知产品人员进行确认。

图片

图3 IM入口样式变化通知


图片

图4 IM入口未显示通知


IM入口监测工具稳定准确地运行了近一年,既能保证IM入口显示正常,也能最大程度上减轻产品运营同学验证的成本,得到了业务线的普遍认可。


6

后续规划


后续我们将继续扩展IM入口巡检工具,对工具本身运行效率进行改进,力争提升入口巡检工具的通用性和可扩展性,可以应用到其他业务中。

作者简介

图片

汽车之家

张慧吉

经销商技术部-移动App团队

汽车报价App技术负责人,在保质保量完成研发任务同时,研发了广告智能截图系统、PhoneBus远程真机平台,不断尝试技术创新创造业务价值。

图片

阅读更多:


▼ 关注「之家技术」,获取更多技术干货 

图片

继续滑动看下一个
之家技术
向上滑动看下一个