新手区 Android Monkey 小记

xinxi · 2018年09月01日 · 最后由 白发苍苍的老大爷 回复于 2018年12月18日 · 2511 次阅读

Android Monkey

Monkey是google提供的一款对Android app进行压力测试工具,基于随机坐标位置,进行点击、滑动、输入等操作.

Monkey的环境配置

  • 1.pc电脑需要配置adb环境
  • 2.Monkey程序由Android系统自带,使用Java语言写,在Android文件系统中的存放路径是:/system/framework/monkey.jar
  • 3.Monkey.jar程序是由一个名为"monkey"的Shell脚本来启动执行,shell脚本在Android文件系统中的存放路径:/system/bin/monkey

常用命令介绍

官方文档

https://developer.android.com/studio/test/monkey

help

adb shell monkey -help 打印参数帮助信息

out:
usage: monkey [-p ALLOWED_PACKAGE [-p ALLOWED_PACKAGE] ...]
[-c MAIN_CATEGORY [-c MAIN_CATEGORY] ...]
[--ignore-crashes] [--ignore-timeouts]
[--ignore-security-exceptions]
[--monitor-native-crashes] [--ignore-native-crashes]
[--kill-process-after-error] [--hprof]
[--pct-touch PERCENT] [--pct-motion PERCENT]
[--pct-trackball PERCENT] [--pct-syskeys PERCENT]
[--pct-nav PERCENT] [--pct-majornav PERCENT]
[--pct-appswitch PERCENT] [--pct-flip PERCENT]
[--pct-anyevent PERCENT] [--pct-pinchzoom PERCENT]
[--pct-permission PERCENT]
[--pkg-blacklist-file PACKAGE_BLACKLIST_FILE]
[--pkg-whitelist-file PACKAGE_WHITELIST_FILE]
[--wait-dbg] [--dbg-no-events]
[--setup scriptfile] [-f scriptfile [-f scriptfile] ...]
[--port port]
[-s SEED] [-v [-v] ...]
[--throttle MILLISEC] [--randomize-throttle]
[--profile-wait MILLISEC]
[--device-sleep-time MILLISEC]
[--randomize-script]
[--script-log]
[--bugreport]
[--periodic-bugreport]
[--permission-target-system]
COUNT

p


查看当前app包名命令:adb shell "dumpsys window |grep mCurrent"

adb shell monkey -p com.test.android(app包名)

启动包名是com.test.androidapp进行monkey测试.

COUNT

adb shell monkey -p com.test.android 300(COUNT)

COUNT是需要Monkey执行的总共事件数.

v

adb shell monkey -p com.test.android -v 100

adb shell monkey -p com.test.android -v -v -v 100

v是设置日志级别,默认是一个

如需更详细的日志可以加多个-v,最多3

s

adb shell monkey -p com.test.android(app包名) -s 50(随机种子)

s表示一个随机种子,必须是数字类型.可以用于两次monkey测试,第二次monkey回归第一次monkey测试出来的bug,指定的随机种子是一样的.
那么两次操作的事件操作基本一致.需要说明的是,随机种子仅仅的是操作是一样的,有些app启动以后会有弹框或者其他引导提醒,那么这样不能保证两次操作的路径是完全一样,需要手工去除

throttle

adb shell monkey -p com.test.android --throttle 500 300

throttle表示两次操作之间的延迟,单位是毫秒.因为实际模拟器用户操作并不一定要操作很快,所以500ms延迟到1000ms接近用户的真实使用.

randomize-throttle

adb shell monkey -p com.test.android --throttle 500 --randomize-throttle 300

randomize-throttle表示每次事件的间隔在0500毫秒之间不固定

pct

触摸事件百分比,即参数--pct-touch
滑动事件百分比,即参数--pct-motion
缩放事件百分比,即参数--pct-pinchzoom
轨迹球事件百分比,即参数--pct-trackball
屏幕旋转事件百分比,即参数--pct-rotation
基本导航事件百分比,即参数--pct-nav
主要导航事件百分比,即参数--pct-majornav
系统事件百分比,即参数--pct-syskeys

adb shell monkey -p com.test.android --pct-touch 20 --pct-motion 30 300

ignore-crashes


adb shell monkey -p com.test.android --ignore-crashes 500

ignore-crashes表示运行monkey,遇到crash会忽略,继续执行后续的操作.

ignore-timeouts

adb shell monkey -p com.test.android --ignore-timeouts 500

ignore-timeouts表示运行monkey,遇到ANR会忽略,继续执行后续的操作.

ignore-native-crashes

adb shell monkey -p com.test.android --ignore-native-crashes 500 

ignore-native-crashes表示忽略monkey本身的异常,直到事件执行完毕

原生monkey一些不足

  • 1.经常能跳出app,又回不去了
  • 2.经常点击顶部导航栏,导致没有网
  • 3.不能对具体页面增加黑名单
  • 4.不能指定运行时间

Monkey脚本化

期望解决上述不足以外,还期望增加如下功能:

  • 1.生成app性能报告并邮件周知
  • 2.自动发送崩溃日志
  • 3.可作为持续集成测试的一部分
  • 4.点击事件更精准,更能点击真实控件

git地址

https://github.com/xinxi1990/MyMonkey.git

脚本框架设计

脚本开发基于python语言开发,大致设计模块如下

脚本执行流程

生成性能报告

配合使用

  • 1.在运行monkey的同时可以测试内存泄漏、卡顿测试、性能监控等,替代一部分重复性手工测试
  • 2.集成到jenkins中是使用,创建一个job,拉android代码打包后执行monkey脚本,比较适合在发版前跑10几个小时

结语

对于app的健壮性和稳定性,一直是个必须关注的问题.传统的手工测试无法解决庞大的用户群体的随机事件,所以此时需要借助一些工具来快速遍历到app中所有功能.

参考文档

android monkey使用教程
https://www.jianshu.com/p/c2aca7019ddf

最佳回复

ignore-native-crashes不是表示忽略monkey本身的异常,直到事件执行完毕。
ignore-native-crashes的作用是忽略运行过程中Android Native层出现的异常,一般是底层C/C++实现的代码层。这个异常出现时系统会在 /data/tombstones 目录下生成 tombstone_xx 的日志文件,记录了应用crash发生时的内存、寄存器、堆栈信息等。
Monkey的处理方式就是,如果有设置--monitor-native-crashes,并且设置了--ignore-native-crashes,则会对Native异常进行监控,在执行每一个事件的时候查看目录/data/tombstones下是否有新的类似tombstone_xx文件生成,下面是AOSP的源码:

/**
* Watch for appearance of new tombstone files, which indicate native
* crashes.
*
* @return Returns true if new files have appeared in the list
*/

private boolean checkNativeCrashes() {
String[] tombstones = TOMBSTONES_PATH.list();
// shortcut path for usually empty directory, so we don't waste even
// more objects
if (tombstones == null || tombstones.length == 0) {
mTombstones = null;
return false;
}
boolean result = false;
// use set logic to look for new files
HashSet<Long> newStones = new HashSet<Long>();
for (String t : tombstones) {
if (t.startsWith(TOMBSTONE_PREFIX)) {
File f = new File(TOMBSTONES_PATH, t);
newStones.add(f.lastModified());
if (mTombstones == null || !mTombstones.contains(f.lastModified())) {
result = true;
waitForTombstoneToBeWritten(Paths.get(TOMBSTONES_PATH.getPath(), t));
Logger.out.println("** New tombstone found: " + f.getAbsolutePath()
+ ", size: " + f.length());
}
}
}
// keep the new list for the next time
mTombstones = newStones;
return result;
}

具体的代码类地址:https://android.googlesource.com/platform/development/+/master/cmds/monkey/src/com/android/commands/monkey/Monkey.java

共收到 6 条回复 时间 点赞

请问在框架中,哪个文件是处理日志的代码~~ 没找到

胡辣汤~~ 回复

logger.py文件中,对logging封装了一次,可以设置log日志级别控制log输出

ignore-native-crashes不是表示忽略monkey本身的异常,直到事件执行完毕。
ignore-native-crashes的作用是忽略运行过程中Android Native层出现的异常,一般是底层C/C++实现的代码层。这个异常出现时系统会在 /data/tombstones 目录下生成 tombstone_xx 的日志文件,记录了应用crash发生时的内存、寄存器、堆栈信息等。
Monkey的处理方式就是,如果有设置--monitor-native-crashes,并且设置了--ignore-native-crashes,则会对Native异常进行监控,在执行每一个事件的时候查看目录/data/tombstones下是否有新的类似tombstone_xx文件生成,下面是AOSP的源码:

/**
* Watch for appearance of new tombstone files, which indicate native
* crashes.
*
* @return Returns true if new files have appeared in the list
*/

private boolean checkNativeCrashes() {
String[] tombstones = TOMBSTONES_PATH.list();
// shortcut path for usually empty directory, so we don't waste even
// more objects
if (tombstones == null || tombstones.length == 0) {
mTombstones = null;
return false;
}
boolean result = false;
// use set logic to look for new files
HashSet<Long> newStones = new HashSet<Long>();
for (String t : tombstones) {
if (t.startsWith(TOMBSTONE_PREFIX)) {
File f = new File(TOMBSTONES_PATH, t);
newStones.add(f.lastModified());
if (mTombstones == null || !mTombstones.contains(f.lastModified())) {
result = true;
waitForTombstoneToBeWritten(Paths.get(TOMBSTONES_PATH.getPath(), t));
Logger.out.println("** New tombstone found: " + f.getAbsolutePath()
+ ", size: " + f.length());
}
}
}
// keep the new list for the next time
mTombstones = newStones;
return result;
}

具体的代码类地址:https://android.googlesource.com/platform/development/+/master/cmds/monkey/src/com/android/commands/monkey/Monkey.java

Viking Den 回复

多谢 又学习了

xinxi 回复

相互学习😀

xinxi 持续集成中的 Android 稳定性测试 中提及了此贴 11月17日 18:58

最长运行时间为毛只有60分钟

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册