Android APP稳定性测试工具Fastbot
<p>我在 自动遍历测试之Monkey工具 和 AppCrawler自动遍历测试 分别介绍了APP稳定性测试工具monkey和AppCrawler,它们各有优缺点,本文介绍另一款也比较好用的稳定性测试工具Fastbot。</p><p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>简介</li><li>前期准备<ul><li>环境</li></ul></li><li>Fastbot遍历测试示例<ul><li>添加限定词</li><li>获取包名</li><li>开启遍历测试</li></ul></li><li>专家系统<ul><li>自定义输入法<ul><li>1. 下载安装ADBKeyBoard</li><li>2. 配置随机输入字符串</li><li>3. 配置fuzzing输入</li></ul></li><li>自定义事件序列</li><li>Activity屏蔽<ul><li>1、Activity白名单配置</li><li>2、Activity黑名单配置</li></ul></li><li>屏蔽控件或区域</li><li>高速截图</li><li>权限自动授予</li></ul></li></ul></div><p></p>
<h1 id="简介">简介</h1>
<p>Fastbot是由字节跳动 Quality Lab开源的一款基于model-based testing 结合机器学习、强化学习的APP 稳定性测试工具,提供了Android和iOS版本。具体原理介绍可参考这篇文章:https://mp.weixin.qq.com/s/QhzqBFZygkIS6C69__smyQ。</p>
<p>本文记录一下Fastbot的使用方法。</p>
<h1 id="前期准备">前期准备</h1>
<h2 id="环境">环境</h2>
<p>本文使用环境:</p>
<ul>
<li>Windows10</li>
<li>Android 10真机</li>
<li>adb 1.0.40</li>
</ul>
<p>adb安装可参考Android ADB原理及常用命令。</p>
<p>使用数据线将手机连接到电脑,到手机设置中的开发人员选择中开启USB调试,电脑命令行输入<code>adb devices</code> 查看手机是否连接成功:</p>
<pre><code class="language-bash">$ adb devices
List of devices attached
CUYDU19626004019 device
</code></pre>
<p>克隆Fastbot_Android项目到本地:</p>
<pre><code class="language-bash">git clone https://github.com/bytedance/Fastbot_Android.git
</code></pre>
<p>然后进入项目目录,将 <code>framework.jar fastbot-thirdpart.jar monkeyq.jar</code> push 到手机<code>/sdcard</code>目录,push <code>libs/* </code> 到 <code>/data/local/tmp/</code>目录:</p>
<pre><code class="language-bash">$ adb push fastbot-thirdpart.jar /sdcard
fastbot-thirdpart.jar: 1 file pushed. 4.1 MB/s (85664 bytes in 0.020s)
$ adb push framework.jar /sdcard
framework.jar: 1 file pushed. 32.3 MB/s (1149240 bytes in 0.034s)
$ adb push monkeyq.jar /sdcard
monkeyq.jar: 1 file pushed. 12.3 MB/s (77375 bytes in 0.006s)
$ adb push libs/. /data/local/tmp/
libs/.\: 4 files pushed. 24.9 MB/s (7740944 bytes in 0.296s)
</code></pre>
<h1 id="fastbot遍历测试示例">Fastbot遍历测试示例</h1>
<p>下面介绍如何使用Fastbot进行简单的遍历测试。</p>
<h2 id="添加限定词">添加限定词</h2>
<p>添加限定词,可提升模型, 使用AAPT2(Android 资源打包工具)解析apk中的索引字符串资源,aapt2是Google Android开发工具包Android SDK中提供的工具,所以要先安装一下Android SDK,下载地址为:http://tools.android-studio.org/index.php/sdk。</p>
<p>安装完成后将aapt2添加到 <code>PATH</code> 环境变量中,我的电脑路径为 <code>D:\android-sdk-windows\build-tools\29.0.3\</code> 。</p>
<p>下面提取要测试APP的apk文件中字符串,以东方财富APP为例,字符提取命令如下:</p>
<pre><code class="language-bash">aapt2 dump strings dfcf_0005564.apk > max.valid.strings
</code></pre>
<p>将<code>max.valid.strings</code>push到手机sdcard目录下:</p>
<pre><code class="language-bash">adb push max.valid.strings /sdcard
</code></pre>
<h2 id="获取包名">获取包名</h2>
<p>接下来读取要测试的APP包名,可以使用aapt2工具:</p>
<pre><code class="language-bash">$ aapt2 dump badging dfcf_0005564.apk
package: name='com.eastmoney.android.berlin' versionCode='10003000' versionName='10.3' platformBuildVersionName='' platformBuildVersionCode='' compileSdkVersion='29' compileSdkVersionCodename='10'
sdkVersion:'16'
targetSdkVersion:'28'
.................
</code></pre>
<p>或者手机打开东方财富,然后执行如下命令:</p>
<pre><code class="language-bash">$ adb shell dumpsys activity activities | findstr mResumedActivity
mResumedActivity: ActivityRecord{a9dd009 u0 com.eastmoney.android.berlin/com.eastmoney.android.module.launcher.internal.search.NewSearchActivity t64017}
</code></pre>
<p>可获取到包名为<code>com.eastmoney.android.berlin</code> 。</p>
<h2 id="开启遍历测试">开启遍历测试</h2>
<p>Fastbot遍历测试命令如下:</p>
<pre><code class="language-bash">adb -s 设备号 shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p 包名 --agent reuseq --running-minutes 遍历时长 --throttle 事件频率 -v -v
</code></pre>
<ol>
<li><code>-s 设备号 </code>:多个设备需要指定设备号,单独设备无需此-s参数</li>
<li><code>-p 包名 </code>:遍历app的包名,-p+包名</li>
<li><code>--agent reuseq </code>:遍历模式,无需更改</li>
<li><code>--running-minutes 遍历时长(分钟)</code> :# 遍历时间:--running-minutes 时间</li>
<li><code>--throttle 事件频率</code> :遍历事件频率,建议为500-800</li>
<li>可选参数
<ul>
<li><code>--bugreport </code>:崩溃时保存bug report log</li>
<li><code>--output-directory /sdcard/xxx</code> :log/crash 另存目录</li>
</ul>
</li>
</ol>
<p>示例:</p>
<pre><code class="language-bash">$ adb -s CUYDU19626004019 shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p com.eastmoney.android.berlin --agent reuseq --running-minutes 1 --throttle 500 -v -v --output-directory /sdcard/fastbot_results&adb pull /sdcard/fastbot_results D:\ProgramWorkspace\DevTest-Notes\APP\Android\Fastbot_Android\results
................
:Sending Touch (ACTION_DOWN): 0:(592.0,412.0)
Wait Event for 633 milliseconds
Events injected: 815
// Monkey is over!
:Sending rotation degree=0, persist=false
Total app activities:
1 com.eastmoney.android.ad.fund.test.FundAdTestMainActivity
2 com.eastmoney.android.cfh.activity.ColumnActivity
3 com.tencent.connect.common.AssistActivity
................
Explored app activities:
1 com.eastmoney.android.account.activity.CMAssistanceActivity
2 com.eastmoney.android.account.activity.PassportLoginActivity
.................
Activity of Coverage: 3.3240995%
:Dropped: keys=0 pointers=11 trackballs=0 flips=0 rotations=0
</code></pre>
<p>打印日志会记录每次操作细节,totalActivity(APP所有activity),ExploredActivity(遍历到的activity列表)以及本次遍历的总覆盖率。</p>
<p>其中Java Crash、ANR、Nativie Crash会以追加方式写入到<code>/sdcard/crash-dump.log</code>文件中,捕获的Anr 同时也会写入 <code>/sdcard/oom-traces.log</code> 文件。</p>
<h1 id="专家系统">专家系统</h1>
<p>不同业务线支持不同的个性化需求,业务深度定制化</p>
<h2 id="自定义输入法">自定义输入法</h2>
<p>ADBKeyBoard在输入栏自动输入内容,屏蔽UI输入法</p>
<p><strong>适用需求:</strong> 遇到搜索栏乱输入,想要输入指定字符</p>
<h3 id="1-下载安装adbkeyboard">1. 下载安装ADBKeyBoard</h3>
<p>下载ADBKeyBoard.apk,adb安装:</p>
<pre><code class="language-bash">$ adb install ADBKeyBoard.apk
Success
</code></pre>
<p>安装完成后设置ADBKeyBoard为默认输入法,设置生效后,点击输入栏时ADBKeyBoard不会弹起ui输入栏。</p>
<h3 id="2-配置随机输入字符串">2. 配置随机输入字符串</h3>
<p>配置输入框可输入的字符串,遍历测试时会随机选择字符输入。</p>
<p>设置配置文件max.config:</p>
<pre><code class="language-text">max.randomPickFromStringList = false # 关闭随机输入字符串
max.randomPickFromStringList = true # 从文件中随机读取字符串
</code></pre>
<p>如果设置 <code>max.randomPickFromStringList = true</code> ,需要编辑 <code>max.strings</code> 文件,输入想要输入的字符串:</p>
<pre><code class="language-text">1 搜索
2 打开
3 检查
</code></pre>
<p>将文件<code>max.config</code> push到手机:</p>
<pre><code class="language-python">adb push max.strings /sdcard
</code></pre>
<h3 id="3-配置fuzzing输入">3. 配置fuzzing输入</h3>
<p>编辑项目中 test 目录下的 <code>max.fuzzing.strings</code>文件,输入想要输入的字符串</p>
<p>将文件push到手机:</p>
<pre><code class="language-bash">adb push test/max.fuzzing.strings /sdcard
</code></pre>
<p>fuzz概率如下:</p>
<pre><code>1. 50% 概率输入fuzzing.strings中某个string
2. 35% 概率输入被测试 App 历史页面中text/desc文本内容(不存在max.fuzzing.strings文件时概率提高到85%)
3. 15% 概率不输入
</code></pre>
<h2 id="自定义事件序列">自定义事件序列</h2>
<p>可以人工配置操作路径,用来覆盖 Fastbot 自动遍历不到的场景。也可以自定义操作序列,设置操作的先后顺序。</p>
<p>1、新建 <code>max.xpath.actions</code> 文件(文件名称不可更改)</p>
<p>2、编写事件序列配置(case):</p>
<ul>
<li><code>prob</code>:发生概率,"prob":1,代表发生概率为100%</li>
<li><code>activity</code>:所属场景,详见:三.获取当前页面所属的Activity</li>
<li><code>times</code>:重复次数,默认为1即可</li>
<li><code>actions</code>:具体步骤的执行类型</li>
<li><code>throttle</code>:action间隔事件(ms)</li>
</ul>
<p>action 支持以下类型:必须大写</p>
<ul>
<li><code>CLICK</code>:点击,想要输入内容在action下补充text,如果有text 则执行文本输入</li>
<li><code>LONG_CLICK</code>:长按</li>
<li><code>BACK</code>:返回</li>
<li><code>SCROLL_TOP_DOWN</code>:从上向下滚动</li>
<li><code>SCROLL_BOTTOM_UP</code>:从下向上滑动</li>
<li><code>SCROLL_LEFT_RIGHT</code>:从左向右滑动</li>
<li><code>SCROLL_RIGHT_LEFT</code>:从右向左滑动</li>
</ul>
<p>下面以东方财富为例:</p>
<pre><code class="language-json">[
{
"prob": 1,
"activity":"com.eastmoney.android.module.launcher.internal.home.HomeActivity",
"times": 1,
"actions": [
{
"xpath":"//*[@resource-id="com.eastmoney.android.berlin:id/et_search"]",
"action": "CLICK",
"text": "600519",
"throttle": 2000
}
]
},
{
"prob": 1,
"activity":"com.eastmoney.android.module.launcher.internal.search.NewSearchActivity",
"times": 1,
"actions": [
{
"xpath":"//*[@resource-id="com.eastmoney.android.berlin:id/rv_search_stock_list"]//*[@text="600519"]",
"action": "CLICK",
"throttle": 2000
}
]
}
]
</code></pre>
<p>编写好文件后,push到手机:</p>
<pre><code class="language-bash">$ adb push max.xpath.actions /sdcard
</code></pre>
<h2 id="activity屏蔽">Activity屏蔽</h2>
<p>手动配置黑、白名单配置,可用来单独覆盖几个场景或屏蔽一些不必要场景。</p>
<h3 id="1activity白名单配置">1、Activity白名单配置</h3>
<p>只覆盖白名单内的activity</p>
<p>1、在PC端新建 <code>awl.strings</code>文件,写入Activity的名称,例如</p>
<pre><code class="language-bash">com.eastmoney.android.module.launcher.internal.home.HomeActivity
</code></pre>
<p>2、将 <code>awl.strings</code> 文件push到手机端的sdcard目录下, 目录必须为sdcard</p>
<pre><code>adb push awl.strings/sdcard
</code></pre>
<p>3、运行命令时添加以下参数:<code>--act-whitelist-file /sdcard/awl.strings</code></p>
<pre><code class="language-bash">adb -s CUYDU19626004019 shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p com.eastmoney.android.berlin --agent reuseq --act-whitelist-file /sdcard/awl.strings --running-minutes 1 --throttle 500 -v -v
</code></pre>
<p>只会遍历白名单内的设置的activity。</p>
<h3 id="2activity黑名单配置">2、Activity黑名单配置</h3>
<p>黑名单内的activity不覆盖</p>
<p>1、新建 <code>abl.strings</code> 文件,在文件中输入Activity的名称,同白名单方法一致</p>
<pre><code class="language-bash">com.eastmoney.android.module.launcher.internal.home.HomeActivity
com.eastmoney.android.msg.center.MsgCenterActivity
com.eastmoney.android.module.launcher.internal.search.NewSearchActivity
com.eastmoney.android.activity.StockActivity
</code></pre>
<p>由于白名单和黑名单不能同时设置,设置了白名单则白名单外的都为黑名单。先把白名单<code>awl.strings</code>文件删掉。</p>
<p>2、然后将<code>abl.strings</code>文件push到手机端的sdcard目录下:</p>
<pre><code class="language-bash">adb push abl.strings/sdcard
</code></pre>
<p>3、运行命令时添加以下参数:</p>
<pre><code>--act-blacklist-file /sdcard/abl.strings
</code></pre>
<pre><code>adb -s CUYDU19626004019 shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p com.eastmoney.android.berlin --agent reuseq --act-blacklist-file /sdcard/abl.strings --running-minutes 1 --throttle 500 -v -v
</code></pre>
<h2 id="屏蔽控件或区域">屏蔽控件或区域</h2>
<p>配置需要屏蔽的控件或区域,比如屏蔽退出登录按钮。</p>
<p>1、新建 <code>max.widget.black</code> 文件,可配置activity、xpath和bounds,比如:</p>
<pre><code class="language-json">[
{
"activity":"com.eastmoney.android.module.launcher.internal.home.HomeActivity",
"xpath": "//*[@resource-id='com.eastmoney.android.berlin:id/et_search']"
},
{
"activity":"com.eastmoney.android.module.launcher.internal.home.HomeActivity",
"bounds":"0,0.87,1,0.95"
}
]
</code></pre>
<p>屏蔽控件或区域共有三种方式:</p>
<ul>
<li><code>bounds</code>:屏蔽某个区域,在该区域内的控件或坐标不会被点击,bounds 为 0.0~1.0 之间的一个百分比值。</li>
<li><code>xpath</code>:查找匹配的控件,屏蔽点击该控件。</li>
<li>xpath+bounds:查找匹配的控件,当控件存在时屏蔽指定的区域。</li>
</ul>
<p>2、将<code>max.widget.black</code>文件push到手机sdcard目录下</p>
<pre><code>adb push max.widget.black /sdcard
</code></pre>
<p>执行:</p>
<pre><code class="language-bash">adb -s CUYDU19626004019 shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p com.eastmoney.android.berlin --agent reuseq --running-minutes 1 --throttle 500 -v -v
</code></pre>
<h2 id="高速截图">高速截图</h2>
<p>保存测试过程中的截图。</p>
<p>1、新建 <code>max.config</code>文件,增加以下属性</p>
<ul>
<li>
<p><code>max.takeScreenshot = true</code></p>
</li>
<li>
<p><code>max.takeScreenshotForEveryStep = true</code></p>
</li>
<li>
<p><code>max.saveGUITreeToXmlEveryStep =true</code></p>
</li>
</ul>
<p>2、将<code>max.config</code> 文件push到手机sdcard目录中:</p>
<pre><code>adb push max.config /sdcard
</code></pre>
<p>添加<code>--output-directory</code>参数指定输出路径, <code>--throttle</code> 参数要 >200 才会截图:</p>
<pre><code>adb -s 设备号 shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p 包名 --agent reuseq --running-minutes 遍历时长 --throttle 事件频率 -v -v --output-directory 指定路径
</code></pre>
<p>示例代码:</p>
<pre><code class="language-bash">adb -s CUYDU19626004019 shell CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar:/sdcard/fastbot-thirdpart.jar exec app_process /system/bin com.android.commands.monkey.Monkey -p com.eastmoney.android.berlin --agent reuseq --running-minutes 1 --throttle 500 -v -v --output-directory /sdcard/fastbot_results&adb pull /sdcard/fastbot_results D:\ProgramWorkspace\DevTest-Notes\APP\Android\Fastbot_Android\results
</code></pre>
<div align="center"> <img src="https://img2022.cnblogs.com/blog/2229336/202210/2229336-20221016144814404-1296799410.png"> </div>
<h2 id="权限自动授予">权限自动授予</h2>
<p>app 的权限弹窗处理, 默认启动app前会自动授予app所需的所有权限,但如果想测试app运行过程中的动态权限弹窗 在 <code>max.config</code> 配置</p>
<ul>
<li>
<p><code>max.grantAllPermission = true</code> Fastbot启动后会自动授予各种权限;</p>
</li>
<li>
<p>shell中增加</p>
<pre><code> -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)
</code></pre>
</li>
</ul>
<p>增加弹窗相关package,可在权限弹窗时关闭弹窗。</p>
<p>Fastbot android APP自动遍历测试就介绍到这里,更多功能可参考官方文档:https://github.com/bytedance/Fastbot_Android/blob/main/handbook-cn.md。</p>
<center><b>--THE END--<b></b></b></center><b><b>
<blockquote>
<p>我的回答之所以发挥作用,原因不是别的,是因为他们自己很努力,如自己不想积极认真的生活,不管得到什么样的回答都没用。——东野圭吾《解忧杂货店》</p>
</blockquote>
</b></b><br><br>
来源:https://www.cnblogs.com/hiyong/p/16796232.html
頁:
[1]