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()对比两张图片,并输出对比结果TrueFalse

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:对话标题,默认为inputThe dialog's title. The default is 'Input'
okTitleThe text to use in the dialog's confirmation button. The default is 'OK'.
cancelTitleThe 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)xy位置处获取一个单个的ARGB像素,参数xy都是基于0坐标,表示一个像素尺寸,x向右增益,y向下增益,得到一个图标的坐标,这个方法返回一个数组

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

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

rectA tuple (x, y, w, h)xy指定矩形区域的左上角,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)

posted @ 2014-11-06 11:10  阳光穿透泛白的记忆  阅读(655)  评论(0编辑  收藏  举报