概述
Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中。它向系统发送伪随机的用户事件流(如按键输入、触摸屏输入、手势输入等),实现对正在开发的应用程序进行压力测试。Monkey测试是一种为了测试软件的稳定性、健壮性的快速有效的方法。Monkey自动化测试工具是可视化操作的便利方式工具,提高使用性和效率。
设置monkey种子数,延迟,执行次数
-s <seed> 种子数作用:伪随机数生成器的seed值。如果用相同的seed值再次运行monkey,将生成相同的事件序列。
--throttle <milliseconds>延迟作用:在事件之间插入固定的时间(毫秒)延迟,你可以使用这个设置来减缓Monkey的运行速度,如果你不指定这个参数,则事件之间将没有延迟,事件将以最快的速度生成。
-v 日志输出等级作用:命令行上的每一个-v都将增加反馈信息的详细级别。
简单(默认),除了启动、测试完成和最终结果外只提供较少的信息。
中等,提供了较为详细的测试信息,如逐个发送到Activity的事件信息。
复杂,提供了更多的设置信息,如测试中选中或未选中的Activity信息。
--ignore-crashes作用:通常,应用发生崩溃或异常时Monkey会停止运行。如果设置此项,Monkey将继续发送事件给系统,直到事件计数完成。
--ignore-security-exception 作用:通常,当程序发生许可错误(例如启动一些需要许可的Activity)导致的异常时,Monkey将停止运行。设置此项,Monkey将继续发送事件给系统,直到事件计数完成。
读取程序包,选择需要测试的包名
-p <allowed-package-name> 程序包作用:如果你指定一个或多个包,Monkey将只允许访问这些包中的Activity。如果你的应用程序需要访问这些包(如选择联系人)以外的Activity,你需要指定这些包。如果你不指定任何包,Monkey将允许系统启动所有包的Activity。指定多个包,使用多个-p,一个-p后面接一个包名。
点击读取程序包通过读取data/data目录下获取所有的程序包名称,首先需要将手机连接到PC,测试连接是否正常,可在cmd里输入adb devices来进行验证;因测试多针对一个特定的APP包,所以需要知道需要测试包的包名;也可以通过 adb shell pm list packages 列出所有包名来进行查找通过全部选择快速选取所有的应用包,通过全部取消取消已选项。
查看log,生成Monkey log。
Monkey开始,通过adb连接手机,并运行logcat,生成logcat到指定目录。
一键monkey可以自动生成默认参数,直接开始monkey测试。
Monkey的可视化界面是通过python 内置的wx模块来实现,可以快速构建UI界面。
软件主界面的控件排布代码:
1. MyFrame是整个窗体的主入口,通过实例化wx.Frame来显示窗口
class MyFrame(wx.Frame):
//设置默认delay时间值
delayDefault = "2"
//设置默认种子数
seedDefault = "5000000"
executionFrequencyDefault = "60000000"
logDir = "./"
def __init__(self):
//执行方式定义
excuteMode = ["忽略程序崩溃",
"忽略程序无响应",
"忽略安全异常",
"出错中断程序",
"本地代码导致的崩溃",
"默认"
]
//日志输出等级区分
logMode = ["简单","普通","详细"]
executionModeDefault = excuteMode[0]
//初始化菜单按钮
menuBar = wx.MenuBar()
menu1 = wx.Menu("")
menuBar.Append(menu1, "File")
self.SetMenuBar(menuBar)
//初始化标签栏
wx.StaticText(panel, -1, "种子数:", pos=(xPos, yPos))
self.seedCtrl = wx.TextCtrl(panel, -1, "", pos=(xPos1, yPos))
//绑定点击事件
self.seedCtrl.Bind(wx.EVT_KILL_FOCUS, self.OnAction)
self.seedCtrl.SetFocus()
//初始化标签栏
wx.StaticText(panel, -1, "执行次数:", pos=(xPos, yPos+yDelta))
//设置窗口位置
self.excuteNumCtrl = wx.TextCtrl(panel, -1, "", pos=(xPos1, yPos+yDelta))
//初始化标签栏
wx.StaticText(panel, -1, "延时:", pos=(xPos, yPos+2*yDelta))
self.delayNumCtrl = wx.TextCtrl(panel, -1, "", pos=(xPos1, yPos+2*yDelta))
//初始化标签栏
wx.StaticText(panel, -1, "执行方式:", pos=(xPos, yPos+3*yDelta))
//设置窗口位置
self.excuteModeCtrl = wx.ComboBox(panel, -1, "", (xPos1,yPos+3*yDelta), choices=excuteMode,style=wx.CB_DROPDOWN)
self.checkListBox = wx.CheckListBox(panel, -1, (xPos, yPos+4*yDelta ), (400, 350), [])
wx.StaticText(panel, -1, "日志输出等级:", pos=(xPos, yPoslayout-yDelta))
self.logModeCtrl = wx.ComboBox(panel, -1, "", (xPos1,yPoslayout-yDelta), choices=logMode,style=wx.CB_DROPDOWN)
//初始化按钮,读取程序包按钮绑定readButton事件
self.readButton = wx.Button(panel, -1, "读取程序包", pos=(xPos, yPoslayout))
self.Bind(wx.EVT_BUTTON, self.OnReadClick, self.readButton)
self.readButton.SetDefault()
//初始化默认参数按钮,绑定defaultButton事件
self.defaultButton = wx.Button(panel, -1, "默认参数", pos=(xPos, yPoslayout+yDelta))
self.Bind(wx.EVT_BUTTON, self.OnResetClick, self.defaultButton)
self.defaultButton.SetDefault()
//初始化一键monkey按钮,按钮绑定quick事件
self.quickButton = wx.Button(panel, -1, "一键Monkey", pos=(xPos+120, yPoslayout+yDelta))
self.Bind(wx.EVT_BUTTON, self.OnQuickStartClick, self.quickButton)
self.quickButton.SetDefault()
def OnBuildLog(self,event):
os.chdir(self.logDir)
date = time.strftime('%Y-%m-%d-%H-%M',time.localtime(time.time()))
dir_m = "Monkey_Log_"+date.replace("-","")
dir0 = "sdcard0_log"
创建目标文件目录
if (os.path.exists(dir_m+"/"+dir0)):
print "already exists"
else:
os.system("mkdir -p "+dir_m+"/"+dir0)
os.chdir(dir_m)
os.system("adb pull /storage/sdcard0/log/ "+dir0)
//查找异常log文件
self.BuildFatalLog(os.getcwd())
def ListFiles(self,path):
//遍历文件件
for root,dirs,files in os.walk(path):
log_f = ""
for f in files:
if(f.find("main") == 0):
log_f = f.strip()
//切换到目标目录
os.chdir(root)
//通过grep 命令查找所有的异常文件
if (log_f != ""):
grep_cmd="grep-Eni-B2-A20'FATAL|error|exception|system.err|androidruntime' "+log_f+" > "+log_f+"_fatal.log"
os.system(grep_cmd)
def BuildFatalLog(self,path):
self.ListFiles(path)
3. 读取程序包代码分析:
//读取程序包函数声明
def OnReadClick(self, event):
//清空控件内容
self.checkListBox.Clear()
//通过读取手机data/data目录来确认所有的包名
os.system("adb shell ls data/data > ~/log.log")
//解析log.log文件
home = os.path.expanduser('~')
f = open(home+"/log.log", 'r')
line = f.readline()
while line:
line = f.readline()
if (line != ""):
print "===="+line
self.checkListBox.Append(line)
f.close()