一、Monkey测试
Monkey测试是一种为了测试软件的稳定性、健壮性的快速有效的方法
Monkey是Android SDK提供的一个命令行工具,可以简单方便的发送随机的用户事件流,对Android APP做压力(稳定性)测试,主要是为了测试app是否存在崩溃与未响应等情况。目前在某些Android应用平台,新版app发布时,平台会执行monkey,检测APP是的稳定性、健壮性;
1、通过adb 启动monkey
a. 在cmd命令行执行:adb devices
查看是移动端设备是否已成功连接(移动端成功连接后才可执行monkey测试)
b. 未连接则执行:adb connect 127.0.0.1:7555(网易mumu模拟器)
c. 通过adb shell monkey命令来启动monkey
例:启动monkey并对设备执行100个随机事件:adb shell monkey -v 100
二、常用参数
命令样例:
adb shell monkey -p com.chan.iambuyer -s 08051351 --pct-touch 25 --pct-motion 15 --pct-pinchzoom 5 --pct-rotation 10 --pct-majornav 25 --pct-flip 10 --pct-syskeys 10 --throttle 500 --ignore-crashes --monitor-native-crashes -v -v -v 5000 >C:\Users\37210\Desktop\MonkeyLog\log.txt
adb shell monkey -p com.xueqiu.android -s 2022042101 --pct-touch 30 --pct-motion 30 --pct-pinchzoom 10 --pct-syskeys 10 --pct-flip 20 --throttle 500 --ignore-crashes --ignore-timeouts --monitor-native-crashes -v-v-v 5000 > /Users/jiejie/Downloads/monkey_logs/logs1.txt
解读:
adb shell monkey
monkey的启动命令
基础参数:
- p
用此参数指定一个或多个包(Package)。指定包之后,Monkey将只允许系统启动指定的APP。如果不指定包,Monkey将允许系统启动设备中的所有APP;
- s
用于为此次测试指定seed的值并记录在log中,不指定则随机生成一数列,若出现问题下次可以重复同样的序列进行复现排错;
- v
用于指定反馈信息级别(信息级别就是日志的详细程度),总共分3个级别,分别对应的参数如下表所示0,1,2分别以-v,-v -v,-v -v -v 表示,建议多以level 2记录测试日志
- v:只提供启动提示、测试完成提示和最终结果等少量信息。
- v -v:较为详细的日志,包括每个发送到activity的时间信息。
- v -v -v:最详细的日志,包括测试中选中/未选中的activity信息。
- -throttle
在每两次操作(即事件)间的时延,单位是毫秒,一般我们设置延时时间为500ms,比较接近人的手动操作,如果在测试中发生了anr,可以将间隔设置为500ms,进行测试验证。
事件类型:
- -pct-touch
指定触摸事件百分比(触碰事件就是指在屏幕上的一个单独位置的一次点击/抬起的事件)
- -pct-motion
指定滑屏事件百分比(由一个在屏幕某处的按下事件、一系列的伪随机移动、一个抬起事件组成,即一个滑动操作);
- -pct-trackball
调整轨迹事件的百分比(轨迹球事件包括一个或多个随机移动,有时还伴有点击。轨迹球现在智能手机上已经没有了,就是类似手柄的方向键一样)
--pct-nav
指定导航事件中,up、down、left、right等事件百分比(老手机的上下左右键,智能机上没有)
- -pct-majornav
指定主要导航事件的百分比(如中间键、取消、确定或菜单引发的图形接口的动作)
- -pct-syskeys
指定系统按键百分比,包括home、Back、音量等
- -pct-appswitch
指定activity之间切换比例
- -pct-flip
键盘轻弹百分比,如点击输入框,键盘弹起,点击输入框以外区域,键盘收回
键盘事件主要是一些与键盘相关的操作。比如点击输入框、键盘弹起、点击输入框以外区域、键盘收回等,这里主要是键盘的打开和关闭操作。
- -pct-pinchzoom
二指缩放,智能机上的放大缩小手势操作事件
二指缩放事件是指在屏幕上的两处同时按下,并同时移动,最后同时抬起的操作,即智能机上的放大缩小手势操作。
- -pct-rotation
屏幕旋转,横屏竖屏事件
屏幕旋转事件是一个隐藏事件,在Android官方文档中并没有记录这个事件。它其实是模拟的Android手机的横屏和竖屏切换。
调试选项:
- -ignore-crashes
用于指定当应用程序崩溃时,Monkey是否停止运行。如果使用此参数,即使应用程序崩溃,Monkey依然会发送事件,直到事件计数完成(即遇到此错误时,monkey继续执行而不退出);
- -ignore-timeouts
用于指定当应用程序发生ANR(Application No Responding)错误时,Monkey是否停止运行。如果使用此参数,即使应用程序发生ANR错误,Monkey依然会发送事件,直到事件计数完成(即遇到此错误时,monkey继续执行而不退出);
- -monitor-native-crashes
用于指定是否监视并报告应用程序发生崩溃的本地代码;
日志中异常关键字:
ANR:程序无响应
###########操作无响应的问题,主要表现在Monkey运行过程中,出现某功能无响应,提示是否“强制关闭“或“等待“##########
// NOT RESPONDING: com.android.soundrecorder (pid 1931)
ANR in process: com.android.soundrecorder (last in com.android.soundrecorder)
Annotation: keyDispatchingTimedOut
CPU usage:
Load: 8.24 / 8.41 / 8.25
CPU usage from 35911ms to 83ms ago:
com.android.soundrecorder: 4% = 3% user + 0% kernel / faults: 997 minor 43 maj
or
mediaserver: 2% = 2% user + 0% kernel / faults: 267 minor 3 major
android.process.media: 2% = 0% user + 1% kernel / faults: 563 minor 194 major
system_server: 1% = 1% user + 0% kernel / faults: 1279 minor 5 major
com.cootek.touchpal: 0% = 0% user + 0% kernel / faults: 180 minor 1 major
sensorserver_ya: 0% = 0% user + 0% kernel / faults: 47 minor 1 major
mmcqd: 0% = 0% user + 0% kernel
app_process: 0% = 0% user + 0% kernel / faults: 203 minor 1 major
com.fihtdc.brservice: 0% = 0% user + 0% kernel / faults: 29 minor
kswapd0: 0% = 0% user + 0% kernel
com.android.settings: 0% = 0% user + 0% kernel / faults: 266 minor
port-bridge: 0% = 0% user + 0% kernel / faults: 19 minor
rpcrouter: 0% = 0% user + 0% kernel
com.android.mms: 0% = 0% user + 0% kernel / faults: 135 minor 8 major
TOTAL: 13% = 8% user + 4% kernel + 0% iowait
procrank:
PID Vss Rss Pss Uss cmdline
1209 35368K 25376K 15283K 14036K system_server
1342 32788K 24596K 14899K 14136K android.process.acore
……
// procrank status was 0
anr traces:
// meminfo status was 0
** System appears to have crashed at event 59034 of 5000000 using seed 0
CRASH:程序崩溃闪退
NullPointerException
**************************************************************************
// CRASH: android.process.acore (pid 1339)
// Short Msg: java.lang.NullPointerException
// Long Msg: java.lang.NullPointerException
// Build Label: android:FIH/msm7627_surf/msm7627_surf/F0X:1.6/DONUT/0001_0_020:e
ng/release-keys
// Build Changelist: -1
// Build Time: 1271397239
// ID:
// Tag: AndroidRuntime
// java.lang.NullPointerException:
// at com.android.launcher.LauncherAnimator.ScrollAnimate3dRotate.drawFrame(ScrollAnimate3dRotate.java:275)
// at com.android.launcher.Workspace.dispatchDraw(Workspace.java:605)
// at android.view.ViewGroup.drawChild(ViewGroup.java:1524)
// at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
// at com.android.launcher.DragLayer.dispatchDraw(DragLayer.java:258)
// at android.view.ViewGroup.drawChild(ViewGroup.java:1524)
// at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
// at android.view.View.draw(View.java:6329)
// at android.widget.FrameLayout.draw(FrameLayout.java:352)
// at android.view.ViewGroup.drawChild(ViewGroup.java:1526)
// at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
// at android.view.View.draw(View.java:6329)
// at android.widget.FrameLayout.draw(FrameLayout.java:352)
// at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1901)
// at android.view.ViewRoot.draw(ViewRoot.java:1333)
// at android.view.ViewRoot.performTraversals(ViewRoot.java:1098)
// at android.view.ViewRoot.handleMessage(ViewRoot.java:1618)
// at android.os.Handler.dispatchMessage(Handler.java:99)
// at android.os.Looper.loop(Looper.java:123)
// at android.app.ActivityThread.main(ActivityThread.java:4203)
// at java.lang.reflect.Method.invokeNative(Method.java:-2)
// at java.lang.reflect.Method.invoke(Method.java:521)
// at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
// at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
// at dalvik.system.NativeStart.main(NativeStart.java:-2)
** System appears to have crashed at event 7908 of 5000000 using seed 0
OutOfMemoryError
#####低内存异常,抛出OutOfMemoryError异常或者是通过kill process 来杀掉部分进程以释放内存空间,当然如果被kill点关键的进程的话,也就可能导致部分应用会自动的退出。出现该情况时,主要是在进行频繁的进行大量的操作导致的#############
// CRASH: com.android.elastos.backup (pid 1581)
// Short Msg: bitmap size exceeds VM budget
// Long Msg: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
// Build Label: android:FIH/msm7627_surf/msm7627_surf/F0X:1.6/DONUT/0001_0_020:eng/release-keys
// Build Changelist: -1
// Build Time: 1271397239
// ID:
// Tag: AndroidRuntime
// java.lang.OutOfMemoryError: bitmap size exceeds VM budget
// at android.graphics.Bitmap.nativeCreate(Bitmap.java:-2)
// at android.graphics.Bitmap.createBitmap(Bitmap.java:464)
// at android.graphics.Bitmap.createBitmap(Bitmap.java:431)
// at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:336)
// at android.widget.AbsListView.preScaleBitmapBG(AbsListView.java:2354)
// at android.widget.AbsListView.draw(AbsListView.java:2365)
// at android.view.ViewGroup.drawChild(ViewGroup.java:1526)
// at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
// at android.view.View.draw(View.java:6329)
// at android.view.ViewGroup.drawChild(ViewGroup.java:1526)
// at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
// at android.view.View.draw(View.java:6329)
// at android.widget.FrameLayout.draw(FrameLayout.java:352)
// at android.view.ViewGroup.drawChild(ViewGroup.java:1526)
// at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
// at android.view.View.draw(View.java:6329)
// at android.widget.FrameLayout.draw(FrameLayout.java:352)
// at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1901)
// at android.view.ViewRoot.draw(ViewRoot.java:1333)
// at android.view.ViewRoot.performTraversals(ViewRoot.java:1098)
// at android.view.ViewRoot.handleMessage(ViewRoot.java:1618)
// at android.os.Handler.dispatchMessage(Handler.java:99)
// at android.os.Looper.loop(Looper.java:123)
// at android.app.ActivityThread.main(ActivityThread.java:4203)
// at java.lang.reflect.Method.invokeNative(Method.java:-2)
// at java.lang.reflect.Method.invoke(Method.java:521)
// at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
// at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
// at dalvik.system.NativeStart.main(NativeStart.java:-2)
** System appears to have crashed at event 143290 of 100000000 using seed 0#
monkey测试顺利完成,日志最后会有monkey finished标识
Monkey测试pass或fail判断1)Monkey finished打开LOG,查看log的最下端,是否有类似以下字段:
Network stats: elapsed time=5123ms (5123ms mobile, 0ms wifi, 0ms not connected)// Monkey finished2)CRASH
同样,在得到日志后,搜索”CRASH”字段,如果搜索到有结果,则表明有进程出现问题,测试不通过。
// CRASH: com.onekchi.downloadmanager (pid 12919)
3)ANR
在Log中搜素该字段,如果有搜索有结果,则表示测试过程中,测试对象出现了无响应的现象,因此测试不通过。--throttle <毫秒>值建议为500
4)Exception
崩溃问题:在日志中搜索“Exception”,快速定位到关键事件信息。
二、adb常用命令
adb 工具即 Android Debug Bridge(安卓调试桥) tools。它就是一个命令行窗口,用于通过电脑端与模拟器或者真实设备交互
- adb devices
主要是用于打印当前连接的所有模拟器或者设备
- adb connect 127.0.0.1:7555
保证设备和 PC 在同一局域网内,连接设备
- adb shell pm list packages
打印设备下所有应用包名
- adb shell pm list packages -3
列表第三方的应用包名
- adb shell pm path <package>
打印apk的路径
- adb shell pm clear <package>
清除指定应用的缓存
- adb uninstall <package>
删除指定应用和所有数据
- adb uninstall -k <package>
删除指定应用,但会保留应用数据和缓存
- adb install <apk_path>
例:adb install C:\Users\37210\Desktop\080402.apk
把pc指定apk包发送到终端并安装
- adb install -r <apk_path>
安装指定路径的apk包,不删除应用数据(更新apk包)
- adb shell screencap <filename>
对手机截取当前页面图片,保存到 filename 下
例:adb shell screencap /sdcard/Pictures/test.png
- adb pull <phone_path> <pc_path>
把手机端 phone_path(源文件地址) 下载到pc本地pc_path(目的地址)下
例:adb pull /sdcard/Pictures/test.png C:\Users\37210\Desktop\app_screen
- adb push <pc_path> <phone_path>
把本地文件推送到手机端
抓取待测app的包名以及启动页的activity
win:
adb logcat ActivityManager:I *:s | findstr "cmp"
mac:
adb logcat "ActivityManager:I *:s" | grep "cmp"
1、执行上面命令,进入抓取app数据状态;
2、命令行抓取到的第一条数据就包含该app的包名以及启动页面的activity
常见问题:adb server is out of date. killing...
通过netstat -nao|findstr "5037"找到对应的端口占用
https://zhuanlan.zhihu.com/p/479207428