1. 项目概述:为什么我们需要告别Monkey?
如果你是一名Android开发或者测试工程师,对“Monkey”这个名字一定不会陌生。作为Android SDK自带的压力测试工具,adb shell monkey命令几乎是每个移动端质量保障流程的起点。它简单、粗暴、无需配置,一个命令就能让应用在设备上“乱点一通”,试图找出那些隐藏的崩溃(Crash)和程序无响应(ANR)问题。在早期,这确实是个快速验证应用稳定性的好方法。
但用久了,你一定会发现它的局限性。Monkey的“随机”更像是“无脑”——它完全无视应用的界面结构和业务逻辑,像一只真正的猴子在键盘上乱敲。这导致测试效率极其低下:大量事件浪费在了状态栏、导航栏或者同一个页面的无效区域;它几乎无法进入应用的深层页面,覆盖率(Activity Coverage)惨不忍睹;更别提针对登录、支付等需要特定操作序列的关键路径进行测试了。你的测试报告里,可能90%的时间都在登录页瞎点,而核心的业务流程一次都没跑通。这种测试,与其说是“压力体检”,不如说是“无效骚扰”。
正是在这种背景下,字节跳动开源的Fastbot进入了我们的视野。它不是一个从零造轮子的新工具,而是一个站在巨人肩膀上的“智能进化版Monkey”。Fastbot继承了Monkey底层高速事件注入的能力,但核心决策引擎从“完全随机”升级为“基于模型的智能化测试”。它通过实时分析应用界面(UI Tree),结合概率模型和强化学习算法,来决定下一次点击哪里“收益”最高——也就是最有可能跳转到新的、未被探索过的页面。这相当于给那只瞎眼的猴子装上了“视觉传感器”和“大脑”,让它能看懂屏幕,并有策略地去探索。
所以,当你需要对你的Android APP进行一次真正有效的“压力体检”,希望不仅发现表面崩溃,更能深入业务场景,提升代码和交互路径的覆盖率时,Fastbot就是你该握在手里的新工具。接下来,我将结合多次实战的经验,带你从零开始,完成一次完整的Fastbot配置与压力测试,并分享那些官方文档里不会写的“避坑指南”。
2. 环境准备与核心组件部署
在开始让Fastbot“跑”起来之前,我们需要准备好它的“身体”和“跑道”。这个过程涉及几个核心组件的获取与部署,虽然步骤稍多,但一旦配置完成,后续使用会非常顺畅。
2.1 获取Fastbot组件包
Fastbot的运行依赖于三个核心的JAR包和一个原生库(.so文件)。对于大多数使用者来说,我们不需要从源码编译,字节跳动已经在GitHub的Release页面提供了编译好的稳定版本。
- 访问仓库:打开Fastbot的GitHub仓库(
github.com/bytedance/Fastbot_Android)。 - 下载Release:在仓库页面,找到并进入“Releases”标签页。选择最新的稳定版本(如
v2.0.0),在Assets部分下载已经打包好的fastbot_android-<version>.jar。这个JAR包通常已经包含了运行所需的所有依赖。 - 解压与提取:将下载的JAR文件重命名为
fastbot.jar(方便后续命令输入)。实际上,官方推荐的方式是使用其内部包含的monkeyq.jar、framework.jar和fastbot-thirdpart.jar。更简单的方法是直接使用他们提供的fastbot.jar,它可能是一个可执行的整体包。为了清晰和兼容性,我建议按照手册准备三个独立的JAR。你可以从Release的附件中找到它们,或者从源码编译(后文会提)。这里假设你已经得到了以下文件:monkeyq.jar(核心Monkey命令扩展)framework.jar(Android框架补丁,用于兼容不同系统)fastbot-thirdpart.jar(第三方依赖,如Gson)libs文件夹(内含armeabi-v7a,arm64-v8a等子目录,存放libfastbot_native.so)
注意:不同Android系统架构(主要是arm64-v8a和armeabi-v7a)需要对应的.so文件。通常
libs文件夹里会包含多个子目录,你需要根据你的测试设备CPU架构来选择。使用adb shell getprop ro.product.cpu.abi命令可以查看设备架构。
2.2 部署组件到测试设备
获取组件后,我们需要将它们推送到Android测试设备(真机或模拟器)的特定位置。这是Fastbot运行时寻找依赖的关键步骤。
- 连接设备:确保你的测试设备已通过USB连接,并开启了USB调试模式。在命令行输入
adb devices,确认设备已列出。 - 推送JAR包:我们将三个JAR包推送到设备的
/sdcard/目录下。这个目录通常对所有应用可读,且路径简单。adb push monkeyq.jar /sdcard/ adb push framework.jar /sdcard/ adb push fastbot-thirdpart.jar /sdcard/ - 推送原生库(.so文件):将对应设备架构的
.so文件推送到/data/local/tmp/目录。这个目录是Unix风格的临时目录,适合存放可执行库文件。假设你的设备是arm64-v8a:
如果adb push libs/arm64-v8a/libfastbot_native.so /data/local/tmp/libs目录下是扁平化的.so文件,直接推送即可。 - 验证推送:可以简单使用
adb shell ls /sdcard/*.jar和adb shell ls /data/local/tmp/*.so来确认文件已存在。
实操心得:
- 路径必须准确:Fastbot启动命令中的
CLASSPATH明确指定了JAR的路径为/sdcard/,而.so库的加载路径是硬编码指向/data/local/tmp/的。推错位置会导致ClassNotFoundError或dlopen failed错误。 - 文件权限:
/data/local/tmp/目录通常权限是rwxrwx--x,.so文件推送后权限正确(如rw-r--r--)即可,一般无需额外chmod操作。 - 模拟器注意:对于Android模拟器,
/sdcard/目录映射到主机的一个路径,同样可用。确保模拟器系统镜像支持你推送的架构。
2.3 获取被测应用的包名
Fastbot需要知道你对哪个应用进行测试,这通过包名(Package Name)来指定。有几种常用方法:
- 通过APK文件获取(推荐):如果你有应用的APK安装包,使用
aapt(Android Asset Packaging Tool)工具最直接。
输出类似# 找到你的Android SDK build-tools目录下的aapt(或aapt2) ${ANDROID_HOME}/build-tools/<version>/aapt dump badging /path/to/your/app.apk | findstr "package: name"package: name='com.example.myapp',com.example.myapp就是包名。 - 通过已安装应用获取:如果应用已经安装在设备上,可以使用
adb shell pm list packages列出所有包,再配合grep(Windows用findstr)过滤。adb shell pm list packages | findstr <你的应用关键词> - 运行时查看顶层Activity:Fastbot自己也提供了一个命令来查看当前屏幕最顶层的Activity及其包名,这在后续配置自定义事件时非常有用。
adb shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey --top-activity
至此,Fastbot的“身体”已经部署到位,我们也明确了测试目标。接下来,就可以启动第一次智能遍历了。
3. 基础运行与参数解析
让我们先抛开所有高级功能,用最基础的命令让Fastbot动起来,感受一下它与原生Monkey的天壤之别。理解核心参数是灵活运用它的基础。
3.1 首次启动与核心参数
一个最基础的Fastbot启动命令如下:
adb shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p com.example.myapp --agent reuseq --running-minutes 10 --throttle 500 -v -v我们来拆解这个命令的每个部分:
adb shell:在设备上执行shell命令。CLASSPATH=...:设置Java类路径,告诉系统在哪里找到我们的三个核心JAR包。这是最容易出错的地方,路径和文件名必须与你推送的完全一致。exec app_process /system/bin com.android.commands.monkey.Monkey:启动Android的monkey命令进程,但通过我们提供的JAR包,其行为已被Fastbot增强。-p com.example.myapp:指定被测应用的包名,将Fastbot的测试范围锁定在该应用内。--agent reuseq:这是关键!这个参数告诉Monkey使用Fastbot的智能代理(agent)模式,而不是原生的随机模式。reuseq是Fastbot内部决策模型的名字。--running-minutes 10:指定测试运行的时长,单位为分钟。这里表示运行10分钟。--throttle 500:设置每个事件之间的延迟,单位为毫秒。500表示每次操作(如点击、滑动)间隔0.5秒。这个值不宜过小(如低于200),否则设备可能反应不过来,导致事件丢失;也不宜过大,否则会降低测试效率。500-800毫秒是一个经过验证的、兼顾稳定性和效率的推荐值。-v -v:设置日志输出级别为“详细”。两个-v比一个-v输出更多信息,方便我们观察Fastbot的决策过程和页面跳转。
执行这个命令后,你应该能在终端看到快速滚动的日志,显示Fastbot正在识别界面元素、计算概率、执行点击。与Monkey的纯粹随机日志相比,Fastbot的日志会包含[State]、[Action]、Choose action based on Q-value等智能决策信息。
3.2 结果解读与覆盖率分析
测试运行结束后(或你使用Ctrl+C中断后),Fastbot会在控制台输出本次测试的总结报告。这是评估测试效果的核心。
你会看到类似这样的输出:
[Fastbot][2023-xx-xx xx:xx:xx.xxx] TotalActivities: 45 [Fastbot][2023-xx-xx xx:xx:xx.xxx] ExploredActivities: 38 [Fastbot][2023-xx-xx xx:xx:xx.xxx] Current Coverage: 84.44%- TotalActivities:Fastbot通过系统接口
PackageManager.getPackageInfo获取到的,该应用声明的所有Activity的数量。请注意:这个列表包含应用内所有Activity,包括那些已经废弃的、作为内部组件的、或通过特定深层链接才能启动的Activity。因此这个数字可能比实际可到达的Activity总数要多。 - ExploredActivities:在本次测试运行中,Fastbot实际成功启动并遍历到的Activity数量。
- Current Coverage:本次测试的Activity覆盖率,计算公式为
(ExploredActivities / TotalActivities) * 100%。84.44%已经是一个相当不错的成绩,远超原生Monkey通常个位数的覆盖率。
除了覆盖率,Fastbot更重要的产出是崩溃日志。任何Java Crash、Native Crash或ANR都会被捕获,并记录到设备的/sdcard/crash-dump.log文件中(ANR还会额外记录到/sdcard/oom-traces.log)。你可以通过adb pull /sdcard/crash-dump.log .将其拉取到电脑上分析。
常见问题与排查:
- 命令执行后立即退出,无任何日志:99%的原因是
CLASSPATH中的JAR包路径错误或文件名不对。请用adb shell ls /sdcard/仔细核对。部分手机系统或文件管理器可能会重命名.jar文件,确保文件名完全一致。 - 报错
Error: Could not load library dlopen failed! libfastbot_native.so:.so文件没有正确推送到/data/local/tmp/目录,或者架构不匹配。请确认推送命令和路径。 - 报错
NoClassDefFoundError:通常是缺少fastbot-thirdpart.jar,或者CLASSPATH中没有包含它。确保三个JAR包都在路径中。 - 测试过程中“点”出了应用,开始点击桌面:检查
-p参数指定的包名是否正确。如果应用进程崩溃后重启失败,Fastbot可能会失去目标。可以增加--kill-process-after-error false参数来阻止Monkey在崩溃后结束测试(但需谨慎,可能陷入崩溃循环)。
4. 专家系统配置:让测试更“懂”业务
基础运行能发现通用问题,但真正的价值在于让自动化测试理解业务。Fastbot的“专家系统”允许我们通过配置文件,干预和引导测试过程,使其能够处理登录、特定流程、屏蔽干扰等复杂场景。这是告别“傻测”的关键。
4.1 自定义输入法:告别乱输入
很多应用都有搜索框、评论框等输入控件。原生Monkey或基础Fastbot可能会在里面输入随机乱码,这虽然是一种Fuzz测试,但很多时候我们更希望它输入一些有意义的测试数据,或者干脆屏蔽输入框,避免无效操作。
解决方案是使用ADBKeyBoard。这是一个虚拟输入法,它不显示UI键盘,而是通过ADB命令接收文本输入。
- 安装与设置:
- 从GitHub等渠道下载
ADBKeyBoard.apk。 - 安装到设备:
adb install ADBKeyBoard.apk。 - 进入手机系统设置 -> 语言与输入法 -> 虚拟键盘,启用“ADBKeyBoard”。
- 在同一设置页面,将默认输入法改为“ADBKeyBoard”。
- 从GitHub等渠道下载
- 配置Fastbot随机输入:
- 在电脑上创建一个名为
max.config的文本文件(文件名固定)。 - 写入配置:
max.randomPickFromStringList = false。这告诉Fastbot从内置的随机字符串池中选取输入。 - 将配置文件推送到设备:
adb push max.config /sdcard/。 - 现在,当Fastbot焦点落在输入框时,ADBKeyBoard会生效,并自动输入随机字符,而不会弹出软键盘。
- 在电脑上创建一个名为
- 配置Fastbot从文件读取输入:
- 如果你有特定的测试数据(如测试账号、搜索关键词),可以创建一个
max.strings文件。 - 每行一个字符串,例如:
test@example.com 软件测试 123456 HelloWorld - 在
max.config中设置:max.randomPickFromStringList = true。 - 推送两个文件:
adb push max.config /sdcard/和adb push max.strings /sdcard/。 - Fastbot会从
max.strings中随机选取一行进行输入。
- 如果你有特定的测试数据(如测试账号、搜索关键词),可以创建一个
4.2 自定义事件序列:引导关键路径
这是专家系统中最强大的功能之一。你可以像编写UI自动化脚本一样,定义一系列精确的操作(点击、输入、滑动),让Fastbot在特定页面执行,从而引导它进入那些通过随机探索难以到达的深层页面,例如“登录-搜索-加入购物车-下单”流程。
配置文件名为max.xpath.actions。其核心结构是一个JSON数组,每个元素是一个“用例”(case)。
[ { "prob": 1, "activity": "com.example.app.ui.login.LoginActivity", "times": 1, "actions": [ { "xpath": "//*[@resource-id='com.example.app:id/et_username']", "action": "CLICK", "throttle": 1000, "text": "testuser" }, { "xpath": "//*[@resource-id='com.example.app:id/et_password']", "action": "CLICK", "throttle": 1000, "text": "password123" }, { "xpath": "//*[@text='登录' or @resource-id='com.example.app:id/btn_login']", "action": "CLICK", "throttle": 2000 } ] }, { "prob": 0.5, "activity": "com.example.app.ui.main.HomeActivity", "times": 1, "actions": [ { "xpath": "//*[@content-desc='搜索栏']", "action": "CLICK", "throttle": 1000 } ] } ]配置解析:
prob: 触发概率,1表示100%触发。可以设置为0.5,表示有50%几率执行这个用例,增加随机性。activity:必须精确匹配。如何获取?运行--top-activity命令(见2.3节),当应用处于目标页面时,执行命令获取完整的Activity名。actions: 动作序列。xpath用于定位控件,这是配置的难点和核心。action: 支持CLICK,LONG_CLICK,BACK,SCROLL_TOP_DOWN等。text: 当action为CLICK且目标控件是可输入的,提供此参数会自动输入文本。throttle: 该动作执行后的等待时间(毫秒),用于等待页面响应。
如何获取精准的XPath?
- 使用Android SDK的
uiautomatorviewer:这是一个图形化工具,可以连接设备,捕获当前屏幕的UI层次结构(XML),并查看每个控件的属性(resource-id, text, class, bounds等)。resource-id是首选的定位方式,因为它通常唯一且稳定。 - 使用Fastbot的DumpTree命令:在终端运行:
这会输出当前页面的UI树文本信息,你可以从中找到控件的属性来组合XPath。例如,adb shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar exec app_process /system/bin tv.panda.test.monkey.api.Dumptree//*[@resource-id='android:id/button1']定位一个确定按钮。
配置心得与避坑:
- Activity匹配是第一步:一定要确保
activity字段的值完全正确,包括大小写和包名。一个字符错误就会导致整个用例不执行。 - XPath优先级:优先使用
resource-id。如果没有,可以组合text和class属性,如//android.widget.Button[@text='确定']。 - 处理页面跳转:如果一个用例里的操作会导致Activity切换(如点击登录按钮跳转到主页),你应该将这个用例拆分成两个,分别对应跳转前和跳转后的Activity。
- 验证JSON:在推送前,将
max.xpath.actions文件内容粘贴到 json.cn 等在线校验工具,确保格式正确,否则Fastbot会静默忽略该文件。 - 推送与生效:
adb push max.xpath.actions /sdcard/。Fastbot启动时会自动读取该文件。
4.3 场景细粒度控制:黑白名单
有时我们只想测试应用的某个模块(如“设置”),或者想屏蔽一些已知不稳定或无关紧要的页面(如开屏广告、第三方登录授权页)。这时就需要黑白名单。
- 白名单 (
awl.strings):只遍历名单内的Activity。- 创建
awl.strings文件,每行一个Activity全名。 - 运行命令添加参数:
--act-whitelist-file /sdcard/awl.strings
- 创建
- 黑名单 (
abl.strings):跳过名单内的Activity。- 创建
abl.strings文件,格式同白名单。 - 运行命令添加参数:
--act-blacklist-file /sdcard/abl.strings
- 创建
重要原则:黑白名单互斥,只能同时使用一种。如果设置了白名单,则名单外的所有Activity都会被当作黑名单处理。黑名单的实现原理是通过Hook拦截Activity启动,因此从UI上看,点击跳转黑名单页面的按钮会“没有反应”。
4.4 屏蔽控件或区域:解决“误触退出”
测试中经常遇到一种尴尬情况:Fastbot不小心点到了“退出登录”或“删除账户”按钮,导致测试会话终止。我们可以通过max.widget.black文件来屏蔽特定控件或屏幕区域。
配置文件格式示例:
activity=com.example.app.ui.profile.SettingActivity bounds=0.9,0.0,1.0,0.1这会在SettingActivity页面,屏蔽屏幕右上角10%的区域(通常可能是“退出”或“设置”图标所在位置)。坐标范围是[left, top, right, bottom],且是相对于屏幕宽高的比例值(0.0~1.0)。
也可以使用XPath精准屏蔽一个按钮:
activity=com.example.app.ui.main.MainActivity xpath=//*[@resource-id='com.example.app:id/btn_logout']推送文件:adb push max.widget.black /sdcard/。Fastbot在遍历时会自动避开这些被屏蔽的元素。
5. 高级功能与实战调优
掌握了基础运行和专家系统,你已经能解决80%的测试场景。下面这些高级功能,则能帮你应对更复杂的情况,并进一步优化测试效率和深度。
5.1 反混淆支持:让配置历久弥新
在大型App开发中,代码混淆是常规操作。这会导致一个问题:你今天通过uiautomatorviewer抓取到的resource-id可能是com.example.app:id/a,但下个版本发布后,它可能变成了com.example.app:id/b。这使得基于XPath的配置(自定义事件、黑白名单、控件屏蔽)在版本迭代后全部失效。
Fastbot支持通过混淆映射文件(mapping file)来解决这个问题。通常,ProGuard或R8等混淆工具在构建APK时会生成一个mapping.txt文件,记录了混淆前后的类名、方法名、字段名对应关系。但resource-id的混淆信息通常在资源混淆(如AndResGuard)产生的resguard-mapping.txt文件中。
操作步骤:
- 从你的构建产物中找到资源混淆映射文件,例如
resguard-mapping-<app>-release.txt。 - 将其重命名为
max.mapping,并推送到设备:adb push resguard-mapping.txt /sdcard/max.mapping。 - 在
max.xpath.actions等配置文件中,使用混淆前的原始resource-id(即开发代码中的ID名,如R.id.btn_login对应的btn_login)。 - 在启动Fastbot的命令中,添加参数:
--resMapping-file /sdcard/max.mapping。
Fastbot会在运行时动态地将你配置中的原始ID,通过映射文件转换为当前版本的实际ID。这样,你的专家系统配置文件就可以在多个版本间通用了,维护成本大大降低。
5.2 高速截图与XML转储:回溯测试现场
“测试时崩溃了,但不知道它点到了哪里。” 这是稳定性测试中的一个常见痛点。Fastbot可以配置在每一步操作后都进行截图并保存当前的UI树结构(XML),为问题回溯提供“现场录像”。
- 创建
max.config文件,添加以下配置:max.takeScreenshot = true max.takeScreenshotForEveryStep = true max.saveGUITreeToXmlEveryStep = true - 推送配置:
adb push max.config /sdcard/。 - 指定输出目录(可选):在启动命令末尾添加
--output-directory /sdcard/fastbot_logs/。如果不指定,截图和XML默认保存在/sdcard/下,以时间戳命名。 - 注意:高速截图功能需要
--throttle参数大于200毫秒,以保证设备有足够时间渲染界面并完成截图。
启用后,/sdcard/目录下会生成大量的.png截图文件和.xml树文件。结合crash-dump.log中的时间戳,你可以精确定位到崩溃发生前最后一刻的屏幕状态和UI结构,极大地方便了开发复现和修复问题。
5.3 Fuzzing与Mutation:引入更多随机“破坏”
除了智能遍历,Fastbot还可以集成Fuzzing(模糊测试)策略,主动注入一些异常或边界情况,尝试触发更深层的缺陷。
- Fuzzing数据集:你可以准备一些畸形的图片、视频、音频文件,推送到设备的
/sdcard/fuzzing/目录。当Fastbot触发到文件选择器时,可能会选中这些文件,测试应用媒体处理模块的健壮性。 - Mutation Event:通过
max.config配置一系列低概率的“变异事件”。例如:
这表示有1%的总概率触发Fuzzing事件,其中如果触发,有15%的概率是突然切换应用到后台再切回,15%的概率是旋转屏幕。这些事件会打断正常的业务流程,模拟用户突然接电话、横竖屏切换等真实场景,有助于发现状态管理相关的Bug。max.fuzzingRate = 0.01D max.doAppSwitchFuzzing = 0.15 max.doRotateFuzzing = 0.15
使用建议:对于常规的稳定性遍历,可以不开或开很低的Fuzzing率。在进行专项的“健壮性测试”或“异常测试”时,可以适当调高这些概率,进行更暴力的测试。
6. 实战避坑指南与性能调优
纸上得来终觉浅,绝知此事要躬行。在实际项目中大规模应用Fastbot,我积累了一些宝贵的经验和踩过的坑,这些在官方手册里往往找不到。
6.1 设备与系统兼容性处理
- MIUI/ColorOS等定制ROM:国内厂商的系统往往有更严格的权限控制。
- 务必开启:开发者选项中的“USB调试(安全设置)”或“允许通过USB调试修改权限或模拟点击”。否则Fastbot的点击事件无法生效。
- OPPO手机:需要在开发者选项中关闭“权限监控”,否则Fastbot进程可能被系统杀死。
- 屏幕常亮:测试长时间运行,务必确保手机屏幕不会自动休眠。可以在开发者选项中设置“保持唤醒状态”,或使用
adb shell svc power stayon true命令。 - 权限弹窗:Fastbot默认会在启动应用前授予所有权限(
max.grantAllPermission = true)。但如果想测试应用运行中的动态权限申请,需将此配置设为false,并在命令中增加权限管理器的包名(如-p com.android.permissioncontroller),这样Fastbot才能帮你点击“允许”。 - 状态栏/导航栏:为了防止测试点到系统设置,Fastbot有时会隐藏状态栏。测试结束后若状态栏未恢复,执行
adb shell wm overscan reset即可重置。
6.2 测试策略与参数调优
- 测试时长:
--running-minutes设置多久?这没有标准答案。对于中型应用,建议首次测试设为30-60分钟。观察覆盖率增长曲线:通常在开始10-20分钟覆盖率快速增长,之后增长放缓。当连续10分钟覆盖率不再变化时,即可停止,说明智能模型已基本探索完当前路径。 - 事件频率:
--throttle是关键性能参数。不建议低于300ms。太快的点击(如100ms)会导致事件队列堆积,界面响应不及,反而降低有效操作率,并可能引发非预期的性能问题。500-800ms是经过多个项目验证的“甜点”区间,能保证设备稳定运行并覆盖足够多的事件。 - 结合CI/CD:将Fastbot集成到自动化流水线中。每晚定时对当日构建的包进行一轮30分钟的Fastbot测试,并收集覆盖率报告和崩溃日志,是建立持续质量反馈环的有效手段。可以使用脚本自动拉取日志、解析覆盖率、发送测试报告。
- 与UI自动化互补:不要用Fastbot完全替代基于脚本的UI自动化。Fastbot擅长探索未知路径和发现随机性崩溃,而UI自动化擅长验证核心业务流程的正确性。两者结合:先用UI自动化脚本确保登录、主流程畅通,然后在这个已登录的状态下启动Fastbot进行深度探索。
6.3 结果分析与问题定位
- 覆盖率不是唯一标准:不要盲目追求100%的Activity覆盖率。如前所述,
TotalActivities包含很多不可达Activity。更应关注ExploredActivities的绝对值是否覆盖了所有核心业务页面。可以结合黑名单,将已知的废弃Activity排除,让覆盖率数据更有参考价值。 - 分析崩溃日志:
crash-dump.log是宝藏。不仅要看崩溃堆栈,更要关注崩溃前Fastbot的执行日志(通过-v -v输出)。配合高速截图功能,可以清晰还原崩溃路径。常见的崩溃类型有:空指针(NPE)、数组越界、内存泄漏(OOM)导致的ANR。 - 处理“假死”:有时Fastbot会卡在某个页面不断重复点击,不再跳转。这可能是该页面有动态加载的内容(如瀑布流),或者某些控件状态异常。此时可以:
- 检查该页面的控件是否被正确识别(用
Dumptree命令)。 - 考虑将该页面加入黑名单
abl.strings,跳过它。 - 或者,为该页面编写一个简短的
max.xpath.actions用例,执行一个“向下滑动”操作,帮助它跳出循环。
- 检查该页面的控件是否被正确识别(用
- 内存与性能监控:长时间运行Fastbot可能会暴露内存泄漏问题。可以在测试前后,通过
adb shell dumpsys meminfo <package_name>命令对比内存占用。如果发现内存持续增长而不回落,就需要提醒开发关注。
6.4 一个完整的实战脚本示例
最后,分享一个我常用的、集成了多项配置的实战脚本模板(Windows批处理示例,Linux/Mac可改为Shell脚本):
@echo off set PACKAGE_NAME=com.example.myapp set DURATION_MINUTES=30 set THROTTLE_MS=500 set DEVICE_SERIAL=emulator-5554 :: 如果是多设备,指定序列号 echo [1/5] 推送必要的文件到设备... adb -s %DEVICE_SERIAL% push monkeyq.jar /sdcard/ adb -s %DEVICE_SERIAL% push framework.jar /sdcard/ adb -s %DEVICE_SERIAL% push fastbot-thirdpart.jar /sdcard/ adb -s %DEVICE_SERIAL% push libs\arm64-v8a\libfastbot_native.so /data/local/tmp/ adb -s %DEVICE_SERIAL% push max.config /sdcard/ adb -s %DEVICE_SERIAL% push max.xpath.actions /sdcard/ 2>nul adb -s %DEVICE_SERIAL% push max.widget.black /sdcard/ 2>nul echo [2/5] 清理旧日志... adb -s %DEVICE_SERIAL% shell rm -f /sdcard/crash-dump.log adb -s %DEVICE_SERIAL% shell rm -f /sdcard/oom-traces.log echo [3/5] 设置设备屏幕常亮... adb -s %DEVICE_SERIAL% shell svc power stayon true echo [4/5] 启动Fastbot智能遍历,时长%DURATION_MINUTES%分钟... adb -s %DEVICE_SERIAL% shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p %PACKAGE_NAME% --agent reuseq --running-minutes %DURATION_MINUTES% --throttle %THROTTLE_MS% --output-directory /sdcard/fastbot_run_%date:~0,4%%date:~5,2%%date:~8,2% -v -v echo [5/5] 测试结束,拉取结果文件... adb -s %DEVICE_SERIAL% pull /sdcard/crash-dump.log . adb -s %DEVICE_SERIAL% pull /sdcard/oom-traces.log . adb -s %DEVICE_SERIAL% pull /sdcard/fastbot_run_%date:~0,4%%date:~5,2%%date:~8,2% ./fastbot_logs/ echo 完成!请查看当前目录下的 crash-dump.log 和 fastbot_logs 文件夹。这个脚本自动化了推送、清理、设置、执行和结果收集的全过程。你可以根据项目需要,在其中灵活添加黑白名单、反混淆等参数。通过这样的实践,Fastbot就不再是一个简单的命令行工具,而是一个强大的、可集成、可定制的自动化稳定性测试解决方案,真正为你的Android应用提供深度的“压力体检”。