稳定性治理--智能遍历

背景

智能遍历,即通智能化的规则来访问APP的UI页面;之所以要考虑这种方式,主要是monkey随机测试,随机性太强,覆盖率不好衡量;不方便进行版本之间的对比,因此考虑其他智能遍历方案,备选的有三种方案“UI自动化实现/appcrawler自动遍历/fastbot智能遍历”

方案对比

  • UI自动化实现

    • 优点
      1
      2
      定制化程度高,可控
      可进行持续集成
    • 缺点
      1
      工作量大,稳定性差,实现难度高
  • appcrawler自动遍历

    • 优点
      1
      2
      3
      4
      覆盖率高,利用类爬虫机制能进行深度遍历,基本覆盖所有的页面
      可进行策略定制,灵活性较高,使用成本较低
      执行有HTML结果,支持Android和iOS渠道
      支持持续集成;
    • 缺点
      1
      执行策略和版本数据相关性不大,无法利用历史策略数据
  • fastbot智能遍历

    • 优点
      1
      2
      3
      4
      5
      6
      7
      8
      9
      覆盖率高,且有覆盖率指标,进行智能遍历,遍历策略较智能(每次遍历都会建模,利用深度学习会持续优化模型,作为驱动策略),现实意义较强;
      可进行定制,灵活度较高,使用成本较低;
      支持iOS和Android渠道;
      可利用数据驱动,方便进行版本间的迭代,方便优化驱动策略;
      支持持续集成;
      利用monkey来遍历,执行较快,效率高;
      支持非标准化控件,可以利用图像识别来进行断言;
      每次的模型可复用,模型文件会自动存储在 /sdcard/fastbot_[包名].fbm,换设备或者版本可复用原有模型,保证策略完全一致;只需要放在相同的位置即可;
      支持多设备
    • 缺点
      1
      2
      3
      需要第三方工具,进行性能监控,本身不支持;
      无结果报告,只有打印的覆盖率指标,同时只有异常日志;
      后期可能会收费,一旦收费,建议转solopi或者自研;

综合考虑,最终决定采用fastbot,其中很大一个原因是其支持数据驱动,方便持续优化策略,同时据同事说shein也在使用;

fastBOT使用

大纲

1
2
3
4
5
6
安装/部署
使用指令
定制策略
优化策略
结果分析
性能采集
  • 安装/部署

    • 部署Java环境
      • 下载java jdk
      • 配置Java环境变量:在系统变量中对JAVA_HOME、PATH、CLASSPATH进行配置:
        • JAVA_HOME:C:\Program Files (x86)\Java\jdk1.8.0_91
        • PATH:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin
        • CLASSPATH:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
    • 部署Android环境
      • 先部署Java环境
      • 安装Android studio
      • 通过Android studio 安装对应版本的Android sdk
      • 添加Android环境变量:系统变量中添加ANDROID_HOME,PATH:
        • ANDROID_HOME:C:\Users\gavin\AppData\Local\Android\Sdk
        • PATH:%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;C:\Users\gavin\AppData\Local\Android\Sdk\build-tools\32.0.0(aapt命令的环境变量,其是apk解析程序)
    • 将jdk包,pull到手机
      • adb push * .jar /sdcard
      • adb push libs/ * /data/local/tmp/
  • 使用指令

    • 举例:
    1
    2
    3
    IOS:tidevice xctest -B bytedance.FastbotRunner112.xctrunner -e 	BUNDLEID:com.TranssnetMusic.Boomplay -e duration:120 -e throttle:300 --debug

    ANDROID:adb -s 037952588D000392 0442233974160287 shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p com.afmobi.boomplayer --agent reuseq --running-minutes 240 --throttle 500 -v -v --output-directory /sdcard/fast_data
    • 参数说明
    1
    2
    3
    4
    5
    6
    7
    8
    9
    必填参数:
    -s imei imei2:支持多设备
    -p package_name:str;“adb shell pm list package”可获取APP包名
    --agent reuseq :遍历模式,无需更改
    --running-minutes 120:遍历时长,单位是min
    --throttle 500:和monkey中的--throttle相同,为事件频率,建议500-800
    选填参数:
    --bugreport :#发生崩溃时打印的日志
    --output-directory : /sdcard/xxx #输出目录的文件夹
  • 定制策略

    • 限定词
      限定自动化定位到的文本只能是apk字符串池中出现的文本,否则抛出异常
      1
      2
      3
      操作:
      aapt2 dump strings apk路径 > max.valid.strings :将apk中所有的字符创,加入到限定词文档
      adb push max.valid.strings /sdcard:配置文件需要push到sdk卡才能生效
    • 自定义事件执行顺序
      应用于需要自定义执行顺序的场景(如登录),或者要保证一定要覆盖到的核心场景,实现方式如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    在pc端新建 max.xpath.actions 文件
    编写事件序列的case,参考我提供的max.xpath.actions文件,文件编写好之后push到/sdcard的根目录;举例说明:
    [
    {
    "prob":1, //事件发生概率,实际使用注释文件要删掉
    "activity":"com.boomplay.ui.main.MainActivity", //作用的页面
    "times":1, //重复次数
    "actions":[ //具体步骤的执行,同时支持多个操作
    {
    "xpath":"//*[@text='Charts']", //尽量使用resource-id作为xpath路径,也可以组合使用比如"xpath": "//*[@resource-id='xxx'and @text='xx']"
    "action":"CLICK", //动作支持的操作,必须大写(CLICK,LONG_CLICK,BACK,SCROLL_TOP_DOWN,SCROLL_BOTTOM_UP,SCROLL_LEFT_RIGHT,SCROLL_RIGHT_LEFT)
    "text": "打开页面成功",
    "clearText":false, //明文,可不带
    "throttle":5000 //action间隔事件(ms)
    },
    {"xpath":"//*[@text='Artists']",
    "action":"CLICK",
    "throttle":5000}
    ]
    }, //到不同的activity操作,需要新起一个对象
    {
    "prob":1,
    "activity":"com.boomplay.ui.guide.GuideDialogSearchActivity",
    "times":1,
    "actions":[
    {
    "xpath":"//*[@text='Charts']",
    "action":"CLICK",
    "text": "打开页面成功",
    "clearText":false,
    "throttle":5000
    },
    {"xpath":"//*[@text='Artists']",
    "action":"CLICK",
    "throttle":5000}
    ]
    },
    ]

    • 配置白名单
      作用:定制策略只在白名单页面内进行操作

      1
      2
      3
      4
      5
      操作:
      新建 awl.strings文件
      在文件中写入Activity的名称,如:com.boomplay.ui.main.MainActivity
      将文件push到手机/sdcard路径下,使用时,在执行命令尾部添加:
      --act-whitelist-file /sdcard/awl.strings
    • 配置黑名单
      作用:定制策略不允许访问黑名单页面

      1
      2
      3
      4
      5
      操作:
      新建 abl.strings文件
      在文件中写入Activity的名称,如:com.boomplay.ui.main.MainActivity
      将文件push到手机/sdcard路径下,使用时,在执行命令尾部添加:
      --act-blacklist-file /sdcard/abl.strings

      黑白名单不能同时配置,非黑即白

    • 定制需要屏蔽的按钮/区域
      作用:如登防止登录后,中途退出

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
          新建max.widget.black文件,文件配置后,push到/sdcard路径下
      [
      {
      "activity":"com.ss.android.xxx.MainActivity",
      "xpath": "//*[@resource-id='com.xxx.go:id/aaa']"//通过元素控制不让访问
      },
      {
      "activity":"com.ss.android.xxx.MainActivity",
      "bounds": 0.5 //activity区域内50%区域不被点击,值为0-1
      }
      ]

    • 通过tree屏蔽
      原理配置xpath:查找匹配的控件,改变控件属性,从而使控件屏蔽

    1
    2
    新建max.tree.pruning文件,文件配置完后,push到/sdcard路径下
    配置实例:建github提供的文件参考配置
    • 定制事件中模糊事件/突发性事件的占比
      所谓的模糊事件,是指执行某个操作后(定制的action事件),模型会根据这个操作生成5-10个相关的操作的策略
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    在max.config文件中增加模糊性事件,在总的事件中的占比,配置完成后,push到/sdcard路径
    max.fuzzingRate = 0.01D //0.01为Fuzz事件的总概率
    模糊事件,包含以下事件,(数字为配置事件在模糊性事件中的概率,以下数值为默认值,可定制):
    max.doRotateFuzzing = 0.15
    max.doAppSwitchFuzzing = 0.15
    max.doTrackballFuzzing = 0.15
    max.doNavKeyFuzzing = 0.15
    max.doKeyCodeFuzzing = 0.15
    max.doSystemKeyFuzzing = 0.15
    max.doDragFuzzing = 0.5
    max.doPinchZoomFuzzing = 0.15
    max.doClickFuzzing = 0.7
    在max.config文件中增加随机性事件(monkey随机性事件),在总的事件中的占比,配置完成后push到/sdcard路径下
    max.startMutation = 0.3D //启动Fastbot立刻设置mutation的几率,默认30%
    随机性事件,包含以下事件,(数字为默认概率,此概率为事件总概率,可定制):
    max.doMutationAirplaneFuzzing = 0.001
    max.doMutationMutationAlwaysFinishActivitysFuzzing = 0.1
    max.doMutationWifiFuzzing = 0.001

  • 优化策略

    • 输入内容优化
      输入是用户主观意愿很强的行为,为保证输入的内容是有价值的,更添近真实场景,在覆盖输入场景做一些策略优化,以屏蔽乱输入内容
    • 操作
    1
    2
    3
    4
    5
    6
    7
    8
    9
    使用ADBKeyBoard在输入栏自动输入内容,屏蔽UI输入法:UI输入法,不同终端使用不同的输入法,不稳定(安装部署adbkeyboard见下方内容,基本所有的开源的自动化工具在输入这块都会封装输入法,为了方便复用和稳定,不建议调用手机的输入法);
    输入随机字符串:pc建一个max.config文件;配置 max.config 中 max.randomPickFromStringList = false,最后将文件push到手机的/sdcard目录下;
    从文件中随机读取字符串来输入:pc建一个max.config文件;配置 max.config 中 max.randomPickFromStringList = true,然后在建一个max.strings文件,里面放用来输入的字符串(每一行为一个对象);最后将max.config和max.strings文件push到手机的/sdcard目录下;
    模糊输入:模糊输入和随机输入有点类似,不过有限定范围,fastbot模糊输入的限定规则如下:
    50% 概率输入fuzzing.strings中某个string
    35% 概率输入被测试 App 历史页面中text/desc文本内容(不存在max.fuzzing.strings文件时概率提高到85%)
    15% 概率不输入
    使用文件限定的模糊输入:将git项目中的test/max.fuzzing.strings文件push到手机/sdcard下,此文件存在模糊搜索策略及生效,文件里放想输入的字符串;

    • 部署adbkeyboard

    • apk反混淆
      是什么:混淆指的是Java混淆编译,用以防止对源码的反编译破解;反混淆,类似于解密;使得配置在 不同版本的App中可以通用

      1
      2
      3
      配置混淆映射文件max.mapping,push到手机/sdcard中,以建立混淆前后ID映射关系:
      adb push resguard_mapping_NewsArticle_beta_version_v7.2.x_?????.txt /sdcard/max.mapping
      配置反混淆文件,以自定义事件为例,在 max.xpath.actions 中配置混淆前的 resource-id,参考示例文件
    • 测试过程中自动截图
      场景:当--throttle 事件频率>200时,配置了截图,会对测试过程中页面进行截图

      1
      2
      3
      4
      5
      新建max.config配置文件,增加以下属性,配置完成后文件push到/sdcard路径下
      max.takeScreenshot = true
      max.takeScreenshotForEveryStep = true
      max.saveGUITreeToXmlEveryStep =true
      目录默认保存为手机端sdcard中,如需改变保存位置,在执行命令末尾添加 --output-directory 指定路径
    • 支持外链跳转
      支持第三方的外链跳转,跳转到第三方应用,或者跳转到端内页面

      1
      2
      3
      新建max.schema文件,增加配置如下,文件配置完后,push到/sdcard路径下
      max.execSchema = true
      max.execSchemaEveryStartup = true #每次启动app先执行schema
    • 应用自动授予权限
      如boomplay需要获取通讯录/相机权限,fastbot启动时默认会一次性各所有权限,如需每次动态给权限,需要更改配置

      1
      2
      3
      4
      5
      6
      7
      在max.config中增加以下配置,则不会自动给所有权限;文件配置完之后push到/sdcard路径下
      max.grantAllPermission = false
      动态给权限的方式是,在执行的adb命令尾部增加对应的android权限授予的指令:
      -p com.android.packageinstaller
      -p com.android.permissioncontroller
      -p com.lbe.security.miui # for (miui android 10)
      -p com.samsung.android.permissioncontroller # for (samsung android 10)
    • fastbot压缩包提供了各类素材,用以在执行选取各类素材的场景中使用,如发带图片的buzz

      1
      2
      adb push data/fuzzing/ /sdcard
      adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///sdcard/fuzzing
  • 结果分析

    • 异常数据
      crash:Crash会以追加方式写入/sdcard/crash-dump.log文件
      anr:写入 /sdcard/oom-traces.log 文件
    • 覆盖率统计:coverage = testedActivity / totalActivities * 100
      testedActivity:本次测试的activity,会打印出来
      totalActivities:总的activity,会打印出来
      以上的所有activity,是不区分废弃,或者未使用的activity,为APP的所有的activity
  • 性能采集
    性能采集,主要是采集内存/CPU的数据,从而来分析APP执行case时的性能

  • 方法一

    通过火山提供的APP性能分析工具进行监控:工具地址(火山引擎开始收费了,工具现在虽然免费,不排除未来收费,有使用风险)

  • 方法二

    借助其他的性能数据抓取工具,比如 OneApm, NewRelic(付费);或者支付宝的solopi;使用第三方工具可能会对结果有影响,最好能统一场景,保证结果一致;

  • 常用操作
  • 获取APP包名

    1
    aapt dump badging apk_path
  • 使用maxim获取APPactivity

    1
    adb shell CLASSPATH=/sdcard/monkey.jar:/sdcard/framework.jar exec app_process /system/bin tv.panda.test.monkey.api.CurrentActivity 注意里面的文件需要push到手机对应的位置后才能使用
  • 使用maxim查看当前页面的TREE结构,来获取配置需要id等。。

    1
    adb shell CLASSPATH=/sdcard/monkey.jar:/sdcard/framework.jar exec app_process /system/bin tv.panda.test.monkey.api.Dumptree
  • 常见问题,查看帮助文档

欢迎关注我的其它发布渠道