monkeyrunner 详细介绍

MonkeyRunner:

monkeyrunner工具提供了一个API,使用此API写出的程序可以在Android代码之外控制Android设备和模拟器。通过monkeyrunner,您可以写出一个Python程序去安装一个Android应用程序或测试包,运行它,向它发送模拟击键,截取它的用户界面图片,并将截图存储于工作站上。monkeyrunner工具的主要设计目的是用于测试功能/框架水平上的应用程序和设备,或用于运行单元测试套件,但您当然也可以将其用于其它目的。

monkeyrunner工具与用户界面/应用程序测试工具,也称为monkey工具并无关联。monkey工具直接运行在设备或模拟器的adbshell中,生成用户或系统的伪随机事件流。而monkeyrunner工具则是在工作站上通过API定义的特定命令和事件控制设备或模拟器。

1、MonkeyRunner的特性

1) 多设备控制:monkeyrunner API可以跨多个设备或模拟器实施测试套件。您可以在同一时间接上所有的设备或一次启动全部模拟器(或统统一起),依据程序依次连接到每一个,然后运行一个或多个测试。您也可以用程序启动一个配置好的模拟器,运行一个或多个测试,然后关闭模拟器。

2) 功能测试:monkeyrunner可以为一个应用自动贯彻一次功能测试。您提供按键或触摸事件的输入数值,然后观察输出结果的截屏。

3) 回归测试:monkeyrunner可以运行某个应用,并将其结果截屏与既定已知正确的结果截屏相比较,以此测试应用的稳定性。

4) 可扩展的自动化:由于monkeyrunner是一个API工具包,您可以基于Python模块和程序开发一整套系统,以此来控制Android设备。除了使用monkeyrunner    API之外,您还可以使用标准的Python ossubprocess模块来调用如adb这样的Android工具。     
您还可以向monkeyrunner API中添加您自己的类。我们将在使用插件扩展monkeyrunner一节中对此进行详细讨论。

2、一个简单的monkeyrunner程序实例

以下为一个简单的monkeyrunner程序,它将会连接到一个设备,创建一个MonkeyDevice对象。使用MonkeyDevice对象,程序将安装一个Android应用包,运行其中一个活动,并向其发送按键事件。程序接下来会将结果截图,创建一个MonkeyImage对象,并使用这个对象截图将保存至.png文件。

# 导入此程序所需的monkeyrunner模块 
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice 
# 连接当前设备,返回一个MonkeyDevice对象 
device = MonkeyRunner.waitForConnection() 
# 安装Android包,注意,此方法返回的返回值为boolean,由此您可以判断安装过程是否正常 
device.installPackage('myproject/bin/MyApplication.apk') 
# 运行此应用中的一个活动 device.startActivity(component='com.android.settings/.Settings') 
# 按下菜单按键 
device.press('KEYCODE_MENU','DOWN_AND_UP') 
# 截取屏幕截图 
result = device.takeSnapShot
# 将截图保存至文件 
result.writeToFile('myproject/shot1.png','png')

#获取指定区域的图像(200,400,200,400),注意两个括号

result_static=result.getSubImage((200,400,200,400))

#获取d:\shotbegin.png这张图片

picture = MonkeyRunner.loadImageFromFile('d:\shotbegin.png','png')

#第二截图并获取相同的局部图像

result_static2=picture.getSubImage((200,400,200,400))

#使用.sameAs()对比两张图片,并输出对比结果True或False

end=result_static.sameAs(result_static2,1.0)

print end

monkeyrunner执行测试时使用.takeSnapshot()截图,默认截取整个屏幕,包含了系统的状态栏。真实手机状态栏中包含如电量/信号量/消息提示等变量,使用.sameAs()对比整个屏幕的截图时就很容易出现错误。而使用.getSubImage()获得局部图像,然后再进行对比,就减少了monkeyrunner执行结果出错的概率。

result.getSubImage((200,400,200,400))中的指定区域值使用Pixel Perfect获取坐标点,或者截图到本地后获取,先获取区域左上角和右下角坐标,前两个值是左上角左边,后两个值是右下角减左上角的坐标。

3、The Monkeyrunner API

monkeyrunnerAPI于com.android.monkeyrunner包中包含三个模块:

1) MonkeyRunner:一个为monkeyrunner程序提供工具方法的类。这个类提供了用于连接monkeyrunner至设备或模拟器的方法。它还提供了用于创建一个monkeyrunner程序的用户界面以及显示内置帮助的方法。

2) MonkeyDevice:表示一个设备或模拟器。这个类提供了安装和卸载程序包、启动一个活动以及发送键盘或触摸事件到应用程序的方法。您也可以用这个类来运行测试包。

3) MonkeyImage :表示一个截图对象。这个类提供了截图、将位图转换成各种格式、比较两个MonkeyImage对象以及写图像到文件的方法。

在python程序中,您将以Python模块的形式使用这些类。monkeyrunner工具不会自动导入这些模块。您必须使用类似如下的from语句:

From com.android.monkeyrunner import MonkeyRunner,MonkeyDevice,MonkeyImage

其中,为您想要导入的类名。您可以在一个from语句中导入超过一个模块,其间以逗号分隔。

4、Monkeyrunner命令语法

4.1 导入需要的模块

① 方式一:

import sys,time,datetime,os

from com.android.monkeyrunner import MonkeyRunner as mr

from com.android.monkeyrunner import MonkeyDevice as md

from com.android.monkeyrunner import MonkeyImage as mi

如果给导入的模块起了别名,就应该使用别名,而不能使用原名,否则会出现错误。

比如连接设备或模拟器,起了以上别名后,命令应该如下:

device=mr.waitForConnection()

② 方式二:

from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice,MonkeyImage

③ 方式三:

import com.android.monkeyrunner

但是在使用时,就显得特别麻烦

device=com.android.monkeyrunner.MonkeyRunner.waitForConnection()

④ 方式四:

我们也可以给它一个别名

import com.android.monkeyrunner as cam

但是在使用时,就显得特别麻烦

device=cam.MonkeyRunner.waitForConnection()

#等待连接到设备,与模拟器连接,返回monkeydevice对象,代表连接的设备。没有报错的话说明连接成功。

参数1:超时时间,单位秒,浮点数。默认是无限期地等待。

参数2:串deviceid,指定的设备名称。默认为当前设备(手机优先,比如手机通过USB线连接到PC、其次为模拟器)。

默认连接:device=MonkeyRunner.waitForConnection()

参数连接:device = mr.waitForConnection(1.0,'emulator-5554')

4.2 向设备或模拟器安装要测试的APK

device.installPackage('myproject/bin/MyApplication.apk') #参数是相对或绝对APK路径

路径级别用“/”,不能用“\”,比如d:\www\a.apk,而应该写成d:/www/a.apk

安装成功返回true,此时查看模拟器我们可以在IDLE界面上看到安装的APK的图标了。

4.3 从设备中删除指定的软件包,包括其相关的数据和调整缓存

device.removePackage('myproject/bin/MyApplication.apk')

删除成功返回true。

4.4 启动任意的Activity

device.startActivity(component="your.www.com/your.www.com.TestActivity")

或者

device.startActivity(component="your.www.com/.TestActivity")

此时可以向模拟器发送如按键、滚动、截图、存储等操作了。

执行一个adb shell命令,并返回结果,如果有的话

device.shell("...")

4.5 暂停目前正在运行的程序指定的秒数

MonkeyRunner.sleep(秒数,浮点数)

4.6 捕捉屏幕写入文件

获取设备的屏蔽缓冲区,产生了整个显示器的屏蔽捕获。(截图)

result=device.takeSnapshot()

返回一个MonkeyImage对象(点阵图包装),我们可以用以下命令将图保存到文件

result.writeToFile('takeSnapshot\\result1.png','png')

MonkeyImage.writeToFile(参数1:输出文件名,也可以包括路径,参数2:目标格式)

写成功返回true,否则返回false

4.7 type

键盘上的类型指定的字符串,这相当于要求每个字符串中的字符按(键码,DOWN_AND_UP).

字符串发送到键盘

device.type('字符串')

4.8 唤醒设备屏幕(在设备屏幕上唤醒)

device.wake()

4.9 重新引导到指定的引导程序指定的设备

device.reboot()

5、Monkeyrunner类的方法介绍

Ø Alert(string message,string title,string okTitle)弹出一个对话框直到用户确认为止

message:会话弹出的内容
     itle:会话标题,默认为alert
     okTitle:会话确认按钮,默认为ok

Ø Choice(string message,iterable choices,string title)显示一个对话框,选择你要添加那个py文件

message:显示在对话框中的提示信息。
choices:一个迭代的包含一系列选择的python类型
title:对话框的标题,默认为input

Ø Help(string format)monkeyrunner 的一些帮助,这个和api差不多

Ø Input(string message,string initialValue,string title,string okTiltle,string cancelTitle)用户可以在一个对话框里面输入内容

用法:MonkeyRunner.input(message,initialValue,title,okTitle,cancelTitle)
message:对话框显示的信息。The prompt message to display in the dialog.
initialValue:提供给用户的初始化值,默认为空字符串。The initial value to supply to the user. The default is an empty string)
title:对话标题,默认为input。The dialog's title. The default is 'Input'
okTitle:The text to use in the dialog's confirmation button. The default is 'OK'.
cancelTitle:The text to use in the dialog's 'cancel' button. The default is 'Cancel'.
返回: The test entered by the user, or None if the user canceled the input;。

Ø Sleep(float seconds)让程序休息多长时间

Ø WaitForConnection(float timeout,string deviceld)等待设备的连接

用法:MonkeyRunner.waitForConnection(timeout,deviceId)
timeout:等待的时间,默认为无限期
deviceId:指定设备名称的一个规定表达式
Returns: 一个表示已经连接的设备对象,A MonkeyDevice object

6、MonkeyDevice类的方法介绍

Ø BroadcastIntent(string uri,string action,string data,string mimetype,iterable categories dictionary extras,component component,iterable flages)对设备发送一个广播信号

uri:信号的uri

Ø Drag(tuple start,tuple end,float duration, integer steps)拖动屏幕,也就是划屏的一些操作

用法:MonkeyDevice.drag(start,end,duration,steps)
start:拖曳开始坐标 - The starting point for the drag (a tuple (x,y) in pixels)
end:拖曳结束坐标点- The end point for the drag (a tuple (x,y) in pixels
duration:持续时间 - Duration of the drag in seconds (default is 1.0 seconds)
steps:拖曳步骤- The number of steps to take when interpolating points. (default is 10)

Ø GetProperty(string key)得到手机上的一些属性

Ø GetSystemProperty(string key)得到一些系统属性

Ø InstallPackage(string path)将一个apk安装到手机里面

Ø Instrument(string className.dictionary args)运行测试设备的指定包

Ø Press(string name,dictionary type)按键(一些物理按键)

Ø Reboot(string into)重启手机

Ø RemovePackage(string package)删除一些apk

Ø Shell(string cmd)执行adb shell命令并返回结果

Ø TakeSnapshot()截图

Ø Touch(integer x,integer y,integer type)触摸

Ø Type(string message)输入一些字符串

Ø Wake()唤醒手机点亮屏幕

7、MonkeyImage类的方法介绍

Ø ConvertToBytes(string format)将图片转换为其他特殊的格式,将结果作为字符串返回,用这个方法将像素存取为特殊的格式,输出的字符串是一种更好的表现

Format:目标格式,默认值为png

Ø GetRawPixel(integer x,integer y)在x,y位置处获取一个单个的ARGB像素,参数x,y都是基于0坐标,表示一个像素尺寸,x向右增益,y向下增益,得到一个图标的坐标,这个方法返回一个数组

Ø GetRawPixelInt(integer x,integer y)得到一个图标的坐标,同上.getRawPixel,只是返回的是一个整型

Ø GetSubImage(tuple rect)复制一个图片的矩形区域

rect:A tuple (x, y, w, h),x,y指定矩形区域的左上角,w为矩形宽,h为矩形高

Ø SameAs(MonkeyImage other,float percent)对比两张图片

Ø WriteToFile(string path,string format)将得到的图片保存到一个文件夹里面

用法:MonkeyImage.writeToFile(path,format)
path:输入的文件名,可选择的包含路径
format:目标格式,默认为png。
return:如果输出成功返回true。

Ø GetHierarchyViewer() 获取设备的显示层次

Ø StartActivity()在设备上开始一个活动

8、MonkeyRunner常用的按键介绍

Ø Home键:KEYCOD_HOME

Back键:KEYCODE_BACK

send键:KEYCODE_CALL

end键:KEYCODE_ENDCALL

上导航键:KEYCODE_DPAD_UP(现在手机已经没有这个键)

下导航键:KEYCODE_DPAD_DOWN(现在手机已经没有这个键)

左导航:KEYCODE_DPAD_LEFT   现在手机已经没有这个键

右导航键:KEYCODE_DPAD_RIGHT 现在手机已经没有这个键

ok键:KEYCODE_DPAD_CENTER

上音量键:KEYCODE_VOLUME_UP

下音量键:KEYCODE_VOLUME_DOWN

power键:KEYCODE_POWER

camera键:KEYCODE_CAMERA

menu键:KEYCODE_MENU

search键:KEYCODE_SEARCH

call键:KEYCODE_CALL

按下HOME键 device.press('KEYCODE_HOME',MonkeyDevice.DOWN_AND_UP)

按下BACK键 device.press('KEYCODE_BACK',MonkeyDevice.DOWN_AND_UP)

按下下导航键 device.press('KEYCODE_DPAD_DOWN',MonkeyDevice.DOWN_AND_UP)

按下上导航键 device.press('KEYCODE_DPAD_UP',MonkeyDevice.DOWN_AND_UP)

按下OK键 device.press('KEYCODE_DPAD_CENTER',MonkeyDevice.DOWN_AND_UP)

device.press('KEYCODE_ENTER',MonkeyDevice.DOWN_AND_UP)#输入回车

device.press('KEYCODE_BACK',MonkeyDevice.DOWN_AND_UP)#点击返回

Monkeyrunner脚本的例子:

Ø 添加联系人脚本:

import sys,time,datetime,os

from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice,MonkeyImage

device=MonkeyRunner.waitForConnection()

MonkeyRunner.sleep(1)

device.startActivity(component='com.android.contacts/.activities.PeopleActivity')

MonkeyRunner.sleep(1)

device.touch(654,1237,'DOWN_AND_UP')

MonkeyRunner.sleep(1)

device.type("yidong")

MonkeyRunner.sleep(1)

device.press('KEYCODE_BACK', MonkeyDevice.DOWN_AND_UP)

MonkeyRunner.sleep(1)

device.touch(293,790,'DOWN_AND_UP')

MonkeyRunner.sleep(1)

device.type("10086")

MonkeyRunner.sleep(1)

device.touch(657,94,'DOWN_AND_UP')

MonkeyRunner.sleep(1)

result = device.takeSnapshot()

result.writeToFile("d:\people.png", "png")

hui=result.getSubImage((200,400,200,400))

picture = MonkeyRunner.loadImageFromFile('d:\people.png','png')

hui1=picture.getSubImage((200,400,200,400))

ggg=hui.sameAs(hui1,1.0)

print ggg

Ø 打电话脚本(用id判断)注:用id判断速度比较慢

import sys,time,datetime,os

from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice,MonkeyImage

from com.android.monkeyrunner.easy import EasyMonkeyDevice,By

device=MonkeyRunner.waitForConnection()

MonkeyRunner.sleep(2)

#device.press('KEYCODE_HOME', MonkeyDevice.DOWN_AND_UP)

#MonkeyRunner.sleep(2)

device.startActivity(component='com.android.contacts/.activities.DialtactsActivity')

MonkeyRunner.sleep(2)

device.touch(By.id('id/one',MonkeyDevice.DOWN_AND_UP)

MonkeyRunner.sleep(1)

device.touch(By.id('id/zero'),'DOWN_AND_UP')

MonkeyRunner.sleep(1)

device.touch(By.id('id/zero'),'DOWN_AND_UP')

MonkeyRunner.sleep(1)

device.touch(By.id('id/eight'),'DOWN_AND_UP')

MonkeyRunner.sleep(1)

device.touch(By.id('id/six'),'DOWN_AND_UP')

MonkeyRunner.sleep(1)

device.touch(By.id('id/dialButtonGreen'),'DOWN_AND_UP')

MonkeyRunner.sleep(10)

#device.touch(By.id('id/one'),'DOWN_AND_UP')

result = device.takeSnapshot()

hui=result.getSubImage((200,400,200,400))

#result.writeToFile("d:\shotbegin.png", "png")

picture = MonkeyRunner.loadImageFromFile('d:\shotbegin.png','png')

hui1=picture.getSubImage((200,400,200,400))

ggg=hui.sameAs(hui1,1.0)

print ggg

MonkeyRunner.sleep(2)

device.press('KEYCODE_BACK', MonkeyDevice.DOWN_AND_UP)

#device.reboot()

MonkeyRunner.sleep(1)

上一篇:用python+selenium从百度获取本地明日的天气信息并根据温度情况设置提醒


下一篇:数据库入门之运行原始 SQL 查找