前言
此博客参考字节跳动技术团队分享,在此由衷感谢!
Fastbot算法原理介绍:https://mp.weixin.qq.com/s/3t4H2bfDjei4vXkj_Cz2pg
1、介绍
基于model-based testing 结合机器学习、强化学习的APP 稳定性测试工具,优势如下:
-
Android多OS兼容
同时兼容Android5-11,兼容国内各⼚商定制化的Android系统及原⽣Android系统 -
事件快速注入
继承原生Monkey的优势,快速点击,每秒最多可发送12个事件 -
专家系统
不同业务线支持不同的个性化需求,业务深度定制化 -
智能化测试
基于model-based 边遍历边建模,利用强化学习等算法做高收益决策 -
跨平台
支持非标准化控件,YOLOv3、ocr、cv分割等UI图像识别能力
2、环境搭建
2.1、源码下载
GitHub地址:https://github.com/bytedance/Fastbot_Android
git clone下来目录如下:
2.2、环境预备
- 支持 Android 5,6,7,8,9,10,11真机及模拟器
- 将 framework.jar , monkeyq.jar push 到手机上某个目录中,建议 /sdcard
adb push framework.jar /sdcard
adb push monkeyq.jar /sdcard
2.3、shell运行
注:若断开USB先执行shell命令,可在命令后,加上&符号
adb -s 设备号 shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p 包名 --agent robot --running-minutes 遍历时长 --throttle 事件频率 -v -v
参数说明:
-s 设备号 #多个设备需要指定设备号,单独设备无需此-s参数
-p 包名 # 遍历app的包名,-p+包名
--agent robot # 遍历模式,无需更改
--running-minutes 遍历时长(分钟) # 遍历时间:--running-minutes 时间
--throttle 事件频率 # 遍历事件频率,建议为500-800
(可选参数)
--bugreport #崩溃时保存bug report log
--output-directory /sdcard/xxx #log\crash 另存目录
结果说明:
-
Crash、ANR 捕获
捕获到Java Crash、ANR、Nativie Crash会以追加方式写入/sdcard/crash-dump.log
文件
捕获的Anr同时也会写入/sdcard/oom-traces.log
文件 -
Activity覆盖率统计
正常跑完Fastbot会在当前shell中打印totalActivity(总activity列表),ExploredActivity(遍历到的activity列表)以及本次遍历的总覆盖率。
总覆盖率计算公式:coverage = testedActivity / totalActivities * 100
如下为Google电话为例(acitity覆盖率为4.76%):
注意事项:
totalActivities:通过framework接口 PackageManager.getPackageInfo 获取,这包含app中所有的Activity,其中也包含了很多废弃、不可用、不可达等Activity。
3、专家系统
3.1、ADBKeyBoard介绍:
"adb shell input text hello"可以通过adb 输入英文的文本,由于不支持unicode编码,所以无法输入中文!ADBKeyBoard是一个虚拟键盘,它接收来自系统broadcast的命令,可以使用ADB输入文本内容,以下是adb 的input事件发生文本。但是,不能使用此命令发送Unicode字符。
GitHub地址:https://github.com/senzhk/ADBKeyBoard
git clone下来目录如下:
通过
adb install [ADBKeyboard.apk 电脑路径]
安装然后在手机端设置ADBKeyboard为默认输入法,cmd控制台输入adb测试效果:
adb shell am broadcast -a ADB_INPUT_TEXT --es msg 测试
手机端显示如下:
3.2、自定义输入法:
ADBKeyBoard在输入栏自动输入内容,屏蔽UI输入法
适用需求:遇到搜索栏乱输入,想要输入指定字符
- 下载ADBKeyBoard,并在手机端中设置为默认输入法,生效后如上图
-
随机输入字符串
配置max.config 中 max.randomPickFromStringList = false
1.在pc端新建max.config
文件(文件名称不可更改)
2.输入max.randomPickFromStringList = false
3.通过adb push max.config /sdcard
命令将max.config文件push到手机端 -
从文件中随机读取字符串输入
配置max.config 中 max.randomPickFromStringList = true
1.在pc端新建max.strings
文件(文件名称不可更改)
2.输入想要输入的字符串,字符串结束要换行
3.通过adb push max.strings /sdcard
命令将max.strings文件push到手机端
3.3、自定义事件序列
手动配置Activity的路径(UI自动化用例)
适用需求:场景覆盖不全,通过人工配置到达Fastbot遍历不到的场景
1.在pc端新建 max.xpath.actions文件(文件名称不可更改)
2.编写事件序列配置(case):
# 谷歌电话示例
[
{
"prob":1,
"activity":"com.google.android.dialer.extensions.GoogleDialtactsActivity",
"times":1,
"actions":[
{
"xpath":"//*[@resource-id='com.google.android.dialer:id/dialpad_fab']",
"action":"CLICK",
"throttle":2000
},
{
"xpath":"//*[@resource-id='com.google.android.dialer:id/search_edit_text']",
"action":"CLICK",
"text":"搜索联系人和地点",
"clearTest":false,
"throttle":2000
}
]
}
]
参数介绍:
prob:发生概率,"prob":1,代表发⽣概率为100%
activity:所属场景(当前页面所属的Activity)
times:重复次数,默认为1即可
actions:具体步骤的执行类型
throttle:action间隔事件(ms)
action参数介绍(必须大写):
CLICK:点击,如果想要输入内容,则在action下补充text,如果有text属性则执行文本输入
LONG_CLICK:长按
BACK:返回
SCROLL_TOP_DOWN:从上向下滚动
SCROLL_BOTTOM_UP:从下向上滑动
SCROLL_LEFT_RIGHT:从左向右滑动
SCROLL_RIGHT_LEFT:从右向左滑动
注:存在页面切换的情况,activity会跳转,则需要对actions进行拆分(同一个activity不需要跳转),从prob开始写下一个activity
3.编写好文件后,在json.cn中检查无误后,通过adb push 路径+max.xpath.actions /sdcard
推送到手机端中
小技巧:adb shell dumpsys window | findstr mCurrentFocus
命令可查看当前应用包名及Activity名
3.4、场景细粒度控制
手动配置黑、白名单配置
适用需求:单独覆盖⼏个场景或屏蔽一些不必要场景
Activity白名单配置(只覆盖白名单内的activity):
- 在PC端新建awl.strings文件(名称固定为:awl.strings)
-
在文件中写入Activity的名称,以换行符分隔
- 通过
adb push awl.strings /sdcard
将awl.strings文件push到手机端的sdcard目录下 - 运行命令时添加以下参数:
--act-whitelist-file /sdcard/awl.strings
Activity黑名单配置(黑名单内的activity不覆盖):
- 在PC端新建abl.strings文件(名称固定为:abl.strings)
- 在文件中输入Activity的名称,同白名单方法一致
- 通过
adb push abl.strings /sdcard
将awl.strings文件push到手机端的sdcard目录下 - 运行命令时添加以下参数:
--act-blacklist-file /sdcard/abl.strings
注:白名单和黑名单不能同时设置,按照非黑即白的原则,即设置了白名单则白名单外的都为黑名单。通过hook 可以监控activity 启动和切换,如果启动的是黑名单中的activity,就拒绝启动该activity,从ui上看就是点了跳转没效果。
3.5、屏蔽控件或区域
手动配置需要屏蔽的控件或区域
适用需求:测试过程中“半路”中途退出登录,屏蔽退出登录按钮
屏蔽控件或区域:
- 在PC端新建max.widget.black文件(名称固定为:max.widget.black)
-
文件内容配置格式如下:
配置activity:当activity与当前activity一致时执行如下匹配
屏蔽控件或区域共有三种方式:
配置bounds:屏蔽某个区域,在该区域内的控件或坐标不会被点击。
配置xpath:查找匹配的控件,屏蔽点击该控件。
配置xpath+bounds:查找匹配的控件,当控件存在时屏蔽指定的区域。
- 通过
adb push max.widget.black /sdcard
推送到手机端中
树剪枝屏蔽:
- 在PC端新建max.tree.pruning文件(名称固定为:max.tree.pruning)
-
文件内容配置格式如下:
配置activity:当activity与当前activity一致时执行如下匹配
剪枝方式:
配置xpath:查找匹配的控件,改变控件属性,从而使控件屏蔽
- 通过
adb push max.tree.pruning /sdcard
推送到手机端中
注:剪枝屏蔽效率更高,但无法作用户于fuzzaction,通常控件区域屏蔽需同时配置黑控件及树剪枝
3.6、反混淆
手动配置反混淆文件,针对每个包的混淆xpath做处理
适用需求:对黑、白名单、屏蔽控件和自定义事件中的xpath做反混淆转换(个人理解:xpath值一样时做一定的转换)
- 配置混淆映射文件并push到手机端sdcard中
adb push resguard_mapping_NewsArticle_beta_version_v7.2.x_?????.txt /sdcard
- 配置反混淆文件,以自定义事件为例,在max.xpath.actions中配置混淆前的id
-
运行命令时添加以下参数:--resMapping-file/sdcard/混淆映射文件
3.7、高速截图及打印xml结构
保存测试过程中的截图和打印xml结构
适用需求:观察测试过程中的截图
- 高速截图保存条件为:
在PC端新建max.config文件,增加以下属性
max.takeScreenshot = true
max.takeScreenshotForEveryStep = true
max.saveGUITreeToXmlEveryStep =true
- 通过
adb push max.config /sdcard
推送到手机端中 - 目录默认保存为手机端sdcard中,如需改变保存位置,在执行命令末尾添加:
--output-directory 指定路径
注:--throttle参数要>200才会截图
3.8、权限自动授予
app的权限弹窗处理,默认启动app前会自动授予app所需的所有权限,但如果想测试app运⾏过程中的动态权限弹窗
在max.config配置:
max.grantAllPermission = false
此时Fastbot启动后不会⾃动授予各种权限;
shell中增加:
-p com.android.packageinstaller
-p com.android.permissioncontroller
-p com.lbe.security.miui (miui android 10)
-p com.samsung.android.permissioncontroller (samsung android 10)
增加其一弹窗相关package,可在权限弹窗时关闭弹窗;