自动遍历概述、为什么要做自动遍历测试、自动遍历测试现状
maxim 的使用、基本参数、高级用法
自动遍历测试概述
monkey测试
提到自动遍历测试,这就不得不提 google 官方的 monkey 测试,但 monkey 测试的初衷并不是为了自动遍历测试,它是为了解决压力测试 / 兼容性测试的,为了测试每个 activity 响应事件的能力。由于它可生成一些伪随机事件,早期很多公司采用 monkey 测试来做兼容性测试和一定程度的自动遍历测试
monkey测试的来源
Monkey 测试这个名字来源于 “无限猴子定理”:即 “让一只猴子一直在打字机上按键,最终能完成莎士比亚的全部工作。” 猴子测试就是百般刁难,乱按一通,系統也不能宕机或者数据出现差错,这样才能称得是经得起考验的程序。
Monkey 测试是 Android 自动化测试里面使用比较简单的方法,可以很大程度检验我们的程序是否稳定,能否经得起压力测试,可以根据实际情况调整测试的强度和测试重点。这个也是在开发 APP 的时候最常用的方法,基本上每个版本发布之前,大家都会进行比较高强度的 Monkey 测试。
它更多针对的不是功能点,而是业务流程。功能点好测,它是明确的。而业务流程难测,它是随机组合的,一切有可能出现的操作,都是一个测试的流程。而我们用例,大部分是正常的业务流程,而异常测试有不可能把所有的流程测到,所以出现了猴子测试的概念。
自动遍历
为什么要进行自动遍历测试?
自动遍历测试的需求是什么?
业务常见问题
- 功能问题
- app 某特定界面崩溃
- app 某接口报错或修改导致老版本数据显示异常
- 某页面详情页特定信息字段内容丢失或数据异常
- 老功能不可用,如微信分享功能
- 兼容性问题
- 网络慢时发出请求退出该页面,当前页面崩溃
- 某些界面在 4.4 或 5.5 系统上操作体验不同
测试痛点
- 无法用 UI 自动化覆盖所有测试场景
- 没有采用合理的分层测试体系,错误的将接口层的测试放在 UI 层
- 没有采用 PageObject 模式,快速迭代的页面变化导致自动化用例维护成本高
- 对自动化框架掌握程度不够,弹窗处理,框架不稳定等情况出现就无法应对
- 自动化测试无法很好支撑一些特殊场景如弱网、某本电子小说翻 1000 页,断言不够灵活
- 测试内容太多导致手工测试无法充分覆盖
- 界面需要校验的字段多
- 接口正确性:后端接口传输数据的变化和内容
- 专项测试回归难度大:内存泄漏、健壮性测试、弱网等测试过程太多
- 回归工作量大:不回归又会漏测
测试手段改进
- 分层测试
- 合理划分接口测试与 UI 测试的比例与业务边界
- 自动化测试覆盖主要业务流程
- 手工测试
- 覆盖新功能测试,探索式测试
- 遍历测试手段
- code less:用例维护成本降到最低
- automate:尽可能的自动化覆盖回归业务
自动遍历测试的需求
- 可控
- 可定义遍历的路径
- 可定制
- 可实现自动输入,自动滑动等基础行为
- 结果可分析
- 点击前后的截图对比
- 结果的数据建模
- 新老版本 / 稳定版本 UI Diff
综上:自动遍历是介于人工测试和自动化测试之间的一种测试手段
自动遍历发展现状
传统的 monkey 测试只能作为稳定性测试 / 兼容性测试工具,且容易卡在某些简单页面,比如登陆页面这种可操作内容很少的页面,又或者经常停留在同一个页面,导致测试效果不佳。但这也给了我们很多的启发,因此就有很多大厂或开发者就尝试对传统的 monkey 测试进行改进,如下(不完全):
- 百度的 SmartMonkey
- 腾讯的 NewMonkey
- 蚂蚁金服 vigossjjj 的 smart_monkey
- 阿里 Macaca 的 NoSmoke
- 熊猫的 zhangzhao 的 Maxim 和 Fastmonkey
- 霍格沃兹测试学院黄延胜的 AppCrawler 及帮助文档
- 新浪 JustinMa 的 UICrawler
- Google 的 App Crawler
Maxim 的使用
基于遍历规则的高性能 Android Monkey,适用于真机 / 模拟器的 APP UI 压力测试
官方文档
初探 maxim
- 下载官方项目 (未开源,提供预编译 jar 包供使用)
- push jar 包到手机 (建议 push 到 / sdcard)
adb push framework.jar /sdcard
adb push monkey.jar /sdcard
- 执行测试命令
adb shell CLASSPATH=/sdcard/monkey.jar:/sdcard/framework.jar exec app_process /system/bin tv.panda.test.monkey.Monkey -p com.panda.videoliveplatform --uiautomatormix --running-minutes 60 -v -v
参数说明
- 兼容 google 官方 monkey 测试参数,如
-p <package_name> --throttle 300 -s 300 -v -v -v
- 测试策略
--uiautomatormix
:混合模式(70% 控件解析随机点击,其余 30% 按原 Monkey 事件概率分布),直接使用底层 accessibiltyserver 获取界面接口解析各控件,随机选取一个控件执行 touch 操作--pct-uiautomatormix n
:可自定义混合模式中控件解析事件概率--uiautomatordfs
: DFS 模式,深度遍历(除 android 5)--uiautomatortroy
:Troy 模式,控件选择策略,按max.xpath.selector
配置的高低优先级来进行深度遍历--act-whitelist-file /sdcard/awl.strings
:定义白名单,awl.strings
控制只在几个特定的 activity 里跑--act-blacklist-file /sdcard/abl.strings
:定义黑名单,abl.strings
控制跳转不会进入到几个特定的 activity 里--running-minutes 60
:设置执行时间
高级用法详解
- 随机输入
max.strings
600519
123456
601857
- 黑白名单
awl.strings
和abl.strings
对跳转做更细粒度控制,比如控制仅在几个特定 Activity 中跑 monkey
adb 命令中需添加参数 --act-whitelist-file /sdcard/awl.strings 定义白名单
--act-blacklist-file /sdcard/abl.string 定义黑名单
com.panda.videoliveplatform.activity.WelcomeActivity
com.panda.videoliveplatform.activity.SplashWakeActivity
com.panda.videoliveplatform.activity.MainFragmentActivity
com.panda.videoliveplatform.activity.LiveRoomActivity
- 配置
max.config
控制 app 启动和唤醒后等待时间、开启截图和开启随机输入开关,保存 pagesource 开关,崩溃回溯图片区间张数
max.startAfterNSecondsofsleep = 6000
max.wakeupAfterNSecondsofsleep = 4000
max.takeScreenShot = true
max.flushImagesThreshold = 20
max.savePageSource = false
max.saveCurrentEventPoint = false
max.randomPickFromStringList = true
takeScreenShot
:开启截图flushImagesThreshold
:崩溃回溯区间图片张数,且需要在 adb 命令中加入参数--imagepolling
- 特殊事件序列
max.xpath.actions
如设置登录事件(需提前安装 ADBKeyBoard)
[
{
"prob": 1,
"activity": "com.android.dazhihui.ui.screen.stock.LoginScreen",
"actions": [
{
"xpath": "//*[@resource-id='com.android.dazhihui:id/switch_login_type']",
"action": "CLICK",
"index": 0,
"throttle": 1000
},
{
"xpath": "//*[@resource-id='com.android.dazhihui:id/loginNick']",
"action": "INPUTTEXT",
"text": "monkeyjerry",
"index": 0,
"throttle": 2000
},
{
"xpath": "//*[@resource-id='com.android.dazhihui:id/loginPwd']",
"action": "INPUTTEXT",
"text": "123456a",
"index": 0,
"throttle": 2000
},
{
"xpath": "//*[@resource-id='com.android.dazhihui:id/confirmBtn']",
"index": 4,
"action": "CLICK",
"throttle": 2000
}
]
}
]
prob
:发生概率activity
:可选,指定则仅在设置的activity
(adb shell dumpsys window w | grep mCurrent
) 执行action
xpath
:控件的xpath,resource-id,class,text,content-desc
或contains
模糊定位(可参考博客 xpath 定位)action
:click,inputtext,touch,swipe,keyevent
特殊事件的 log 如何查看?
Maxim
运行开头会打印出load
的Special Event
- 解析生成
tree
结构如0|2|1|2|5|6,.....
表示index|height|depth|childCount|descendantCount,className,contentDesc,text,xpath,clickable,rect
,然后针对xpath
进行查找,找到则打印Find it
- 黑空间和黑区域屏蔽
max.widget.black
屏蔽某些界面的某些空间或者区域,如屏蔽广告区域
[
{
"activity": "com.panda.videoliveplatform.activity.MainFragmentActivity",
"xpath": "//*[@class='android.widget.TextView' and @text='我的校园' and @resource-id='com.panda.videoliveplatform:id/tv_title']"
},
{
"activity": "com.panda.videoliveplatform.activity.MainFragmentActivity",
"xpath": "//*[@class='android.widget.TextView' and @text='车队' and @resource-id='com.panda.videoliveplatform:id/tv_title']",
"index": 0,
"bounds": "[0,633][900,789]"
},
{
"activity": "com.panda.videoliveplatform.activity.MainFragmentActivity",
"bounds": "[0,1107][900,1263]"
}
]
仅配置
bounds
屏蔽某个区域,在该区域内的控件或坐标不会被点击
仅配置xpath
查找匹配的控件,屏蔽点击该控件
同时配置xpath+bounds
则查找匹配的控件,当控件存在时屏蔽指定的区域
Troy
模式max.xpath.selector
控制控件优先级
控件选择策略会按 1first 2select 3last 执行并屏蔽 black 来执行遍历
[
{
"firstList":
[
{ "xpath": "//*[contains(@text,'绝地求生')]" }
],
"selectList":
[
{ "xpath": "//*[@clickable='true']" },
{ "xpath": "//*[@clickable='true']//*[contains(name(),'Text')]" },
{ "xpath": "//*[@clickable='true']//*[contains(name(),'Button')]" },
{ "xpath": "//*[@clickable='true']//*[contains(name(),'Image')]" }
],
"lastList":
[
{ "xpath": "//*[../*[@selected='true']]" },
{ "xpath": "//*[../../*/*[@selected='true']]" },
{ "xpath": "//*[../../*/*[@selected='true'] and contains(@resource-id,'tab_')]" },
{ "xpath": "//*[contains(@resource-id,'HorizontalScrollView')]" }
],
"blackList":
[
{ "xpath": "//*[contains(@resource-id,'wrapper_in_custom_title_bar')]//*[contains(@resource-id,'right_button')]" },
{ "xpath": "//*[contains(@resource-id,'share')]" }
]
}
]
我的 maxim 配置
adb push framework.jar /sdcard
adb push monkey.jar /sdcard
adb install ADBKeyBoard.apk
adb shell rm -rf /sdcard/Android/data/.dzh
adb shell pm clear com.android.dazhihui
adb shell rm -rf /sdcard/log_error_dzh.txt
adb push max.xpath.actions /sdcard
adb push max.config /sdcard
adb push max.strings /sdcard
- mix
adb shell CLASSPATH=/sdcard/monkey.jar:/sdcard/framework.jar exec app_process /system/bin tv.panda.test.monkey.Monkey -p com.android.dazhihui --throttle 500 --imagepolling --uiautomatormix --running-minutes 60 -v -v>d:/monkey.log
- dfs
adb shell CLASSPATH=/sdcard/monkey.jar:/sdcard/framework.jar exec app_process /system/bin tv.panda.test.monkey.Monkey -p com.android.dazhihui --throttle 500 --imagepolling --uiautomatordfs --running-minutes 60 -v -v>d:/monkey.log
参考
- 基于 Android Monkey 二次开发,实现高速点击的 Android Monkey
- seveniruby(霍格沃兹测试学院黄延胜)的自动遍历测试分享