Android-monkey稳定性测试(多台设备同时进行)

时间:2022-03-16 09:52:05

                                  

1.目的(原创文章,转载请注明出处~)

主要为指引开展android平台应用的稳定性测试,尽可能地在应用发布前发现crash及anr等问题并修复,android平台的应用均适用并可定制接入。

主要达到下班前执行,第二天上班时查看分析测试日志的目的,实现了以下核心功能:

a、可批量同时对多台android手机进行测试;

b、可对一台android设备选择模式为连续多次测试;

c、输入保存monkey运行时日志文件和用logcat抓取app运行时日志

2.环境搭建

3.1、java jdk环境配置:安装jdk,并添加系统环境变量,点击参考

3.2、android sdk环境配置(建议使用方法2):

方法1:下载安装SDK for Windows:

设置sdk下面tools的环境变量

右击“计算机”-》属性-》高级系统设置-》环境变量-》

点击Path,将“D:\android-sdk-windows\platform-tools”添加到变量值中,与之前的变量值用“;”隔开。

方法2:可通过安装android模拟器的方式实现(较简单),可直接搜索下载droid 4x海马玩模拟器。

安装成功后设置环境变量:

右击“计算机”-》属性-》高级系统设置-》环境变量-》

点击Path,将“D:\Program Files\Droid4X”添加到变量值中,与之前的变量值用“;”隔开。

3.3、python环境搭建:安装python 2.7或3.5版本,并添加系统环境变量,点击参考

3.测试前准备

2.1、每台待测android设备手工安装好待测试app应用,若为需要登录才能使用app功能的应用请先手工完成登录操作,并确保跳过相应的app新手引导页。

2.2、待测试android设备通过USB数据线与PC主机相连,并通过360手机助手之类的工具确保手机与pc是可进行adb调试的)。如下所示,在cmd命令中输入adb devices,所列的设备如果状态为device则代表该设备已可与PC通过adb调试通信。(建议一台PC机所连接android设备不超过5)

2.3、执行monkey测试前,一定要确保屏幕处于解锁状态。设置屏幕超时时间为最大时间(设置->显示->休眠->30分钟或者从不)。以防测试过程中手机锁屏,影响monkey测试。

4.测试工具介绍

4.1 monkey工具

Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中。它向系统发送伪随机的用户事件流(如按键输入、触摸屏输入、手势输入等),实现对正在开发的应用程序进行测试。Monkey测试是一种为了测试软件的稳定性、健壮性的快速有效的方法。点击详细了解monkey

4.2 adb工具

Android调试桥接器,简称adb,是用于管理模拟器或真机状态的万能工具。Adb工具在本稳定性测试方案中主要作为PC与手机的通信桥梁。点击详细了解adb

4.3 python脚本功能说明

此脚本可以达到同时进行多台手机的测试,并可选择单次测试和同一台设备多次连续测试,具体功能说明如下:

Python脚本执行说明:在pc上快捷键“win+R”打开cmd命令行,输入:python E:\monkey_test\monkey_dist.py(脚本的绝对路径)

 # -*- coding: GB2312 -*-
 import os
 import os.path
 import time
 import glob

 # 删除已有测试cmd脚本
 path = "E:\\monkey_test\\"
 for file in glob.glob(os.path.join(path, '*.cmd')):
     os.remove(file)

 os.system("cls")  # os.system("cls")具有清屏功能
 rt = os.popen('adb devices').readlines()  # os.popen()执行系统命令并返回执行后的结果
 n = len(rt) - 2
 print "当前已连接待测手机数为:" + str(n)
 aw = raw_input("是否要开始你的monkey测试,请输入(yes or no): ")

 if aw == 'yes':
     print "monkey测试即将开始...."
     count = raw_input("请输入你要进行的monkey测试次数: ")
     testmodel = raw_input("请输入你是要进行单次测试还是多次连续测试,请输入(1-代表单次测试,2-代表多次连续测试): ")
     ds = range(n)
     for i in range(n):
         nPos = rt[i + 1].index("\t")
         ds[i] = rt[i + 1][:nPos]
         dev = ds[i]
         promodel = os.popen(
             "adb -s " + dev + ' shell cat /system/build.prop | find "ro.product.model="').readlines()  # 获取手机型号
         #modelname = ('').join(promodel)  # 将list转为字符串
         modelname = promodel[0] #从list中取出第一个值
         model = modelname[17:].strip('\r\n')
         proname = os.popen(
             "adb -s " + dev + ' shell cat /system/build.prop | find "ro.product.brand="').readlines()  # 获取手机名称
         roname = proname[0]
         name = roname[17:].strip('\r\n')
         packagename = os.popen(
             "adb -s " + dev + ' shell pm list packages | find "xxx"').readlines()
         package = packagename[0]
         pk = package[8:].strip('\r\n')
         if pk == 'com.xxx':
             filedir = os.path.exists("E:\\monkey_test\\")
             if filedir:
                 print "File Exist!"
             else:
                 os.mkdir("E:\\monkey_test\\")
             devicedir = os.path.exists("E:\\monkey_test\\" +name + '-' + model + '-' + dev)
             if devicedir:
                 print "File Exist!"
             else:
                 os.mkdir("E:\\monkey_test\\" +name + '-' + model + '-' + dev)  # 按设备ID生成日志目录文件夹
             wl = open("E:\\monkey_test\\" +name + '-' + model + '-' + ds[i] + '-logcat' + '.cmd', 'w')
             #wl.write('adb -s ' + dev + ' logcat -v time ACRA:E ANRManager:E System.err:W *:S')
             wl.write('adb -s ' + dev + ' logcat -v time *:W')
             wl.write('> E:\\monkey_test\\' + '"'+ name  + '-'+ model + '-' + dev + '"' + '\\logcat_%random%.txt\n')
             wl.close()
             ':
                 wd = open("E:\\monkey_test\\" +name + '-' + model + '-' + ds[i] + '-device' + '.cmd', 'w')
                 wd.write(
                          'adb -s ' + dev + ' shell monkey -p com.xxx --monitor-native-crashes --ignore-crashes --pct-syskeys 5 --pct-touch 55 --pct-appswitch 20 --pct-anyevent 20 --throttle 200 -s %random% -v ' + count)  # 选择设备执行monkey
                 wd.write('> E:\\monkey_test\\' + '"'+ name  + '-'+ model + '-' + dev + '"' + '\\monkey_%random%.txt\n')
                 wd.write('@echo 测试成功完成,请查看日志文件~')
                 wd.close()
             ':
                 wd = open("E:\\monkey_test\\" +name + '-' + model + '-' + ds[i] + '-device' + '.cmd', 'w')
                 wd.write(':loop')
                 wd.write('\nset /a num+=1')
                 wd.write('\nif "%num%"=="4" goto end')
                 wd.write(
                          '\nadb -s ' + dev + ' shell monkey -p com.xxx --monitor-native-crashes --ignore-crashes --pct-syskeys 5 --pct-touch 55 --pct-appswitch 20 --pct-anyevent 20 --throttle 200 -s %random% -v ' + count)  # 选择设备执行monkey
                 wd.write('> E:\\monkey_test\\' + '"'+ name  + '-'+ model + '-' + dev + '"' + '\\monkey_%random%.txt\n')
                 wd.write('@echo 测试成功完成,请查看日志文件~')
                 wd.write('\nadb -s '+ dev +' shell am force-stop '+ pk)
                 wd.write('\n@ping -n 15 127.1 >nul')
                 wd.write('\ngoto loop')
                 wd.write('\n:end')
                 wd.close()
         else:
             print "请确认待测手机"+name + '-' + model +"未安装com.xxx~"

     # 执行上述生成的cmd脚本path='E:\\monkey_test\\'
     for file in os.listdir(path):
         if os.path.isfile(os.path.join(path, file)) == True:
             if file.find('.cmd') > 0:
                 os.system('start ' + os.path.join(path, '"' + file + '"'))  # dos命令中文件名如果有空格,需加上双引号
                 time.sleep(1)
 elif aw == 'no':
     print('请重新确认所有待测手机是否已通过adb命令连接至pc!')
 else:
     print "测试结束,输入非法,请重新输入yes or no!"

1.查找当前已连接的测试设备;

Android-monkey稳定性测试(多台设备同时进行)

2.设置当前要进行的monkey测试次数;

Android-monkey稳定性测试(多台设备同时进行)

3.设置要进行的测试模式:单次or 多次连续;

Android-monkey稳定性测试(多台设备同时进行)

4.完成1~3步后,会由python生成相应的android设备的cmd批处理脚本,然后自动扫描执行所有已生成的批处理脚本,以进行monkey稳定性测试。

Android-monkey稳定性测试(多台设备同时进行)

5、测试结果分析

查看测试日志(进入日志文件夹E:\monkey_test,目前会同时保存monkey运行时的日志和logcat抓取app运行时的实时日志,monkey日志主要关注是否含关键字: crash、exception、anr,logcat日志主要关注是否含关键字:E/ACRA和weloop相关的exception。目前先手工搜索进行检查,日志分析工具后续提供~)

Android-monkey稳定性测试(多台设备同时进行)

如下所示,某次测试中导致APP崩溃的现象,logcat日志如下(将有效的异常日志提交给相应的开发同学进行确认问题所在):

06-03 14:04:26.730 E/ACRA    ( 9152): ACRA caught a RuntimeException exception for com.xx.xxx.xxx.xxx. Building report.

06-03 14:04:27.229 W/ActivityManager(  718): Activity pause timeout for ActivityRecord{2e729252 u0 com.xx.xxx.xxx.xxx./pl.gatti.dgcam.DgCamActivityForTommy2 t874 f}

06-03 14:04:28.238 W/recents.Performance(  934): preload while task Change spend : 1

06-03 14:04:29.761 E/ACRA    ( 9152): com.xx.xxx.xxx.xxx. fatal error : Unable to pause activity {com.xx.xxx.xxx.xxx./pl.gatti.dgcam.DgCamActivityForTommy2}: java.lang.RuntimeException: Camera is being used after Camera.release() was called

06-03 14:04:29.761 E/ACRA    ( 9152): java.lang.RuntimeException: Unable to pause activity {com.xx.xxx.xxx.xxx./pl.gatti.dgcam.DgCamActivityForTommy2}: java.lang.RuntimeException: Camera is being used after Camera.release() was called

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3613)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3568)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3543)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.app.ActivityThread.access$1000(ActivityThread.java:178)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1557)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.os.Handler.dispatchMessage(Handler.java:111)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.os.Looper.loop(Looper.java:194)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.app.ActivityThread.main(ActivityThread.java:5779)

06-03 14:04:29.761 E/ACRA    ( 9152):       at java.lang.reflect.Method.invoke(Native Method)

06-03 14:04:29.761 E/ACRA    ( 9152):       at java.lang.reflect.Method.invoke(Method.java:372)

06-03 14:04:29.761 E/ACRA    ( 9152):       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1005)

06-03 14:04:29.761 E/ACRA    ( 9152):       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:800)

06-03 14:04:29.761 E/ACRA    ( 9152): Caused by: java.lang.RuntimeException: Camera is being used after Camera.release() was called

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.hardware.Camera.lock(Native Method)

06-03 14:04:29.761 E/ACRA    ( 9152):       at pl.gatti.dgcam.a.b(ProGuard:76)

06-03 14:04:29.761 E/ACRA    ( 9152):       at pl.gatti.dgcam.DgCamActivityForTommy2.l(ProGuard:555)

06-03 14:04:29.761 E/ACRA    ( 9152):       at pl.gatti.dgcam.DgCamActivityForTommy2.onPause(ProGuard:547)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.app.Activity.performPause(Activity.java:6215)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1363)

06-03 14:04:29.761 E/ACRA    ( 9152):       at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3595)

06-03 14:04:29.761 E/ACRA    ( 9152):       ... 11 more

附:常见问题

1、脚本检测出来的手机数与待测手机数不一致,此时需要手工检查确认是否所有手机USB连接/USB调试模式均已打开;

2、部分华为手机权限未放开,导致logcat未能捕获monkey执行测试时的应用日志;如提示:

则华为手机进入拨号界面输入:*#*#2846579#*#* 依次选择:工程菜单---后台设置----LOG设置---LOG开关 将四个选项点击打开。

3、因为monkey工具为随机事件测试,故会误打开系统的音乐播放器播放音乐。