简介
看《西游记》第五十七回,说是“六耳猕猴”化作孙悟空的摸样,伤了唐僧,后又和孙悟空大打出手…… 这位假孙悟空,实力不用多说了吧,和真孙悟空一般无二,大战孙悟空,闹到上天入地下海。 在唐僧那:念紧箍咒,两个都喊疼,自然看不出哪个真假; 到天宫:拖塔天王拿照妖镜照,也看不出; 又到观音那:观音也看不出。最后到幽冥处阎罗那,经“谛听”听过之后,“谛听”却说:“我看出来了,却不敢说” 最后还是如来老佛爷道出六耳真身并用金钵盂罩住,才被孙悟空一棍子打死。想必各位小伙伴都看过这以精彩片段。不过据知情人士说真假美猴王存在阴谋,这里有黑幕:说是真的孙悟空被打死了,活下来的是假的。好了废话少说,还是回到今天的主题:真假美猴王Monkeyrunner与Monkey傻傻的分不清楚。
今天宏哥就带着各位小伙伴和童鞋们再当一回和尚:如来佛祖辨一辨真假美猴王,前边我们已经对monkey做过一些详细的介绍和讲解,今天我们就再来介绍和讲解一下monkeyrunner。看看他们之间的到底是一样还是有区别的。
monkeyrunner简介
1.monkeyrunner工具使用Jython,这是一种使用Java编程语言的Python实现。Jython允许monkeyrunner API与Android框架轻松交互。使用Jython,您可以使用Python语法来访问API的常量,类和方法。MonkeyRunner工具是使用Jython(使用Java编程语言实现的
Python)写出来的,它提供了多个API,通过monkeyrunner API 可以写一个Python的程序来模拟操作控制Android设备app,测试其稳定性并通过截屏可以方便地记录出现的问题。
2.我们来看一下monkeyrunner官网是如何介绍monkeyrunner的:
官网介绍(已翻译成中文)宏哥在这里给小伙伴截取一段翻译,如下:
monkeyrunner工具提供了一个API,用于编写从Android代码外部控制Android设备或模拟器的程序。使用monkeyrunner,您可以编写一个Python程序,安装Android应用程序或测试包,运行它,向其发送击键,截取其用户界面,并在工作站上存储屏幕截图、
monkeyrunner工具主要用于测试功能/框架级别的应用程序和设备以及运行单元测试套件,但您可以将其用于其他目的。
monkeyrunner工具与UI / Application Exerciser Monkey无关 ,也称为monkey工具。该monkey工具adb直接在设备或仿真器上的shell中运行, 并生成用户和系统事件的伪随机流。相比之下,monkeyrunner工具通过从API发送特定命令和事件来控制工作站中的设备和
仿真器。
3.monkeyrunner即android SDK中自带的工具之一,此工具提供API可按制android设备或模拟器。
4.有兴趣的小伙伴们或者童鞋可以查看一下monkeyrunner官网:https://www.android-doc.com/tools/help/monkeyrunner_concepts.html
5.monkeyrunner 路径:Andriod_SDK ools
MonkeyRunner工具独特功能
1.多设备控制:monkeyrunner API可以跨多个设备或仿真器应用一个或多个测试套件。您可以物理连接所有设备或立即启动所有模拟器(或两者),以编程方式依次连接到每个设备,然后运行一个或多个测试。您还可以以编程方式启动模拟器配置,运行一个或多个测试,然后关闭模拟器。
2.功能测试:monkeyrunner可以对Android应用程序进行自动化的从头到尾的测试。您可以通过击键或触摸事件提供输入值,并将结果视为屏幕截图。
3.回归测试 - monkeyrunner可以通过运行应用程序并将其输出屏幕截图与一组已知正确的屏幕截图进行比较来测试应用程序的稳定性。
4.可扩展的自动化 - 由于monkeyrunner是一个API工具包,您可以开发一个基于Python的模块和程序的整个系统来控制Android设备。除了使用monkeyrunner API本身,您还可以使用标准的Python os
和 subprocess
模块来调用Android工具,例如 Android Debug Bridge。
您还可以将自己的类添加到monkeyrunner API中。这在“ 使用插件扩展monkeyrunner ”一节中有更详细的描述 。
Monkeyrunner与Monkey区别
monkeyrunner和money没有什么直接的关系,monkey是在设备直接运行adb shell命令生成随机事件来进行测试的。相比较而言,monkeyrunner则是通过API发送特定的命令和事件来控制设备。
为了支持黑盒自动化测试的场景,Android SDK提供了monkey和monkeyrunner两个测试工具,这两个测试工具除了名字类似外,还都可以向待测应用发送按键等消息,往往容易产生混淆,以下是他俩的不同之处。
Monkey:
Monkey工具直接运行在设备或模拟器的adb shell中,生成用户或系统的伪随机事件流。
1.monkey运行在设备或者模拟器上边,可以脱离PC运行,其运行时如下图所示。
Monkeyrunner:
Monkeyrunner工具是在工作站上通过API定义的特定命令和事件控制设备或模拟器。
而monkeyrunner运行在PC上,需要通过服务器/客户端的的模式向设备或者模拟器上的android应用发送指令来执行测试,其运行时如下图所示。
2.普遍的做法是将monkey作为一个向待测应用发送随机按键消息的测试工具,验证待测应用在这些随机性的输入面前是否会有闪退或者崩溃。而monkeyrunner则接受一个明确的测试脚本(使用python语言编写的)。
3.虽然monkey也可以根据一个指定的命令脚本发送按键消息,但其不支持条件判断,也不支持读取界面的信息来执行验证操作。而monkeyrunner的测试脚本中有明确 的条件判断等语句,可用来做功能测试。
总结:
实际操作中,monkey由于缺少必要的条件判断等命令,难以在功能测试上有所作为,只能作为生成一些随机事件的工具,测试应用程序的健壮程度,待测应用崩溃后可以根据monkey打印的日志,再用monkey创建一个重现步骤,供开发调试。monkey服务器模式更适合用于黑盒测试,不建议用于自动化测试。
而Monkeyrunner虽然有Python和Java类库的强大支持,但其自身提供的API有限,还得需要插件扩展其功能。
monkeyrunner API
monkeyrunner API包含在包中的三个模块中 com.android.monkeyrunner
:
1.MonkeyRunner
:monkeyrunner程序的一类实用方法。此类提供了将monkeyrunner连接到设备或模拟器的方法。它还提供了为monkeyrunner程序创建UI以及显示内置帮助的方法。
2.MonkeyDevice
:表示设备或模拟器。此类提供了安装和卸载软件包,启动Activity以及向应用程序发送键盘或触摸事件的方法。您还可以使用此类来运行测试包。
3.MonkeyImage
:表示屏幕捕获图像。此类提供捕获屏幕,将位图图像转换为各种格式,比较两个MonkeyImage对象以及将图像写入文件的方法。
在Python程序中,您可以将每个类作为Python模块进行访问。monkeyrunner工具不会自动导入这些模块。要导入模块,请使用Python from
语句:
1 from com.android.monkeyrunner import <module>
<module>
您要导入的类名 在哪里。from
通过用逗号分隔模块名称,可以在同一语句中导入多个模块。
运行monkeyrunner
您可以从文件中运行monkeyrunner程序,也可以在交互式会话中输入monkeyrunner语句。您可以通过调用SDK目录子目录中的monkeyrunner
命令来执行这两项操作tools/
。如果提供文件名作为参数,则该monkeyrunner
命令将文件的内容作为Python程序运行; 否则,它会启动一个交互式会话。
该monkeyrunner
命令的语法是
1 monkeyrunner -plugin <plugin_jar> <program_filename> <program_options>
表1解释了标志和参数。
参数 | 描述 |
---|---|
-plugin <plugin_jar> |
(可选)指定.jar 包含monkeyrunner插件的文件。要了解有关monkeyrunner插件的更多信息,请参阅 使用插件扩展monkeyrunner。要指定多个文件,请多次包含该参数。 |
<program_filename> |
如果提供此参数,则该monkeyrunner 命令将该文件的内容作为Python程序运行。如果未提供参数,则该命令将启动交互式会话。 |
<program_options> |
(可选)<program_file>中程序的标志和参数。 |
运行monkeyrunner
命令语法为:
方式一:在CMD命令窗口直接运行monkeyrunner
方式二:使用Python编写测试代码文件,在CMD中执行monkeyrunner hongge.py运行
不论使用哪种方式,您都需要调用SDK目录的tools子目录下的monkeyrunner命令。
附:这部分前边已经讲解过,在这里就不再赘述)
问题:CMD运行提示monkeyrunner不是内部或外部命令,也不是可运行的程序或批处理文件。
解决:电脑环境变量未配置,将monkeyrunner所在目录配在环境变量里。
变量名:Path
变量值:D:androidandroid-sdk-windows ools;D:androidandroid-sdk-windowsplatform-tools
实例
实例一:卸载旧的APP,安装新的APP
*准备
a. 连接安卓夜神模拟器设备
b. 运行CMD,检测是否连接成功
CMD>adb devices
附:(这部分前边已经讲解过,在这里就不再赘述)
问题:CMD运行提示adb不是内部或外部命令,也不是可运行的程序或批处理文件。
解决:电脑环境变量未配置,将adb所在目录配在环境变量里。
*方式一:
1.打开CMD,运行monkeyrunner
2.进入monkeyrunner的shell命令交互模式后,逐条输入以下命令
2 device = MonkeyRunner.waitForConnection()
3 device.removePackage('com.taobao.taobao')
4 device.installPackage('C:\Users\DELL\Desktop\702757.apk')
(1)输入命令前的夜神模拟器:
(2)输入第三行命令后的夜神模拟器
(3)输入第四行的夜神模拟器
注:每条命令的作用,请见方法二中的注解
实操如图:
c.检查手机app是否已更新
*方式二:
a. 编写Python测试代码
1 # File: Test1.py 2 # Vision: V1.0 3 # Author: hongge QQ群:707699217 4 # 引入本程序所用到的模块 5 from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage 6 7 # 连接手机设备 8 device = MonkeyRunner.waitForConnection() 9 10 # 截图 11 result = device.takeSnapshot() 12 # 将截图保存到文件 13 result.writeToFile('E:\JAVA\monkeyrunner\Test1\Test1_001.png','png') 14 15 # 卸载APP 16 device.removePackage('cn.richinfo.thinkdrive') 17 print ('Uninstall Success!') 18 19 # 暂停5秒 20 MonkeyRunner.sleep(5) 21 22 # 截图 23 result = device.takeSnapshot() 24 result.writeToFile('E:\JAVA\monkeyrunner\Test1\Test1_002.png','png') 25 26 # 安装新的APP 27 device.installPackage('E:\JAVA\monkeyrunner\Test1\ThinkDrive_new.apk') 28 print ('Install Success!') 29 30 # 截图 31 result = device.takeSnapshot() 32 result.writeToFile('E:\JAVA\monkeyrunner\Test1\Test1_003.png','png')
注:拷贝运行时请去掉中文注释;或者在开头加入 #coding=utf-8
b.执行Test1.py脚本
Monkeyrunner C:UsersDELLDesktop est.py
实操如图:
c.检查手机app是否已更新
d.查看截图文件夹,截图和上边逐条输入命令,宏哥截得模拟器一模一样的。
e.注意如果截图不一样自己加个等待时间,就会一样,参考代码:
1 #coding=utf-8 2 # File: Test1.py 3 4 # Vision: V1.0 5 6 # Author: hongge QQ群:707699217 7 8 # 引入本程序所用到的模块 9 10 from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage 11 12 13 14 # 连接手机设备 15 16 device = MonkeyRunner.waitForConnection() 17 18 19 20 # 截图 21 22 result = device.takeSnapshot() 23 24 # 将截图保存到文件 25 26 result.writeToFile('C:\Users\DELL\Desktop\test\Test1_001.png','png') 27 28 29 30 # 卸载APP 31 32 device.removePackage('com.taobao.taobao') 33 34 print ('Uninstall Success!') 35 36 37 38 # 暂停5秒 39 40 MonkeyRunner.sleep(5) 41 42 43 44 # 截图 45 46 result = device.takeSnapshot() 47 48 result.writeToFile('C:\Users\DELL\Desktop\test\Test1_002.png','png') 49 50 51 # 暂停5秒 52 53 MonkeyRunner.sleep(5) 54 55 56 # 安装新的APP 57 58 device.installPackage('C:\Users\DELL\Desktop\702757.apk') 59 60 print ('Install Success!') 61 62 # 暂停5秒 63 64 MonkeyRunner.sleep(5) 65 66 # 截图 67 68 result = device.takeSnapshot() 69 70 result.writeToFile('C:\Users\DELL\Desktop\test\Test1_003.png','png')
monkeyrunner内置帮助
您可以通过运行以下命令为monkeyrunner生成API参考:
1 monkeyrunner help.py <format> <outfile>
论点是:
<format>
或者是text
纯文本的输出或html
用于HTML输出。<outfile>
是输出文件的路径限定名称。
使用插件扩展monkeyrunner
您可以使用Java编程语言编写的类扩展monkeyrunner API,并将其构建为一个或多个.jar
文件。您可以使用此功能使用您自己的类扩展monkeyrunner API或扩展现有类。您还可以使用此功能初始化monkeyrunner环境。
要为monkeyrunner提供插件,请monkeyrunner
使用表1中-plugin <plugin_jar>
描述的参数 调用该命令 。
在你的插件代码,你可以导入和扩展的主要monkeyrunner类 MonkeyDevice
,MonkeyImage
和MonkeyRunner
在com.android.monkeyrunner
(见的monkeyrunner API)。
请注意,插件不允许您访问Android SDK。您无法导入包等com.android.app
。这是因为monkeyrunner与框架API级别下的设备或模拟器交互。
插件启动类
.jar
插件 的文件可以指定在脚本处理开始之前实例化的类。要指定此类,请将密钥添加 MonkeyRunnerStartupRunner
到.jar
文件的清单中。该值应该是启动时要运行的类的名称。以下代码段显示了如何在ant
构建脚本中执行此操作:
1 <jar jarfile="myplugin" basedir="${build.dir}"> 2 <manifest> 3 <attribute name="MonkeyRunnerStartupRunner" value="com.myapp.myplugin"/> 4 </manifest> 5 </jar>
要访问monkeyrunner的运行时环境,启动类可以实现 com.google.common.base.Predicate<PythonInterpreter>
。例如,此类在默认命名空间中设置一些变量:
1 package com.android.example; 2 3 import com.google.common.base.Predicate; 4 import org.python.util.PythonInterpreter; 5 6 public class Main implements Predicate<PythonInterpreter> { 7 @Override 8 public boolean apply(PythonInterpreter anInterpreter) { 9 10 /* 11 * Examples of creating and initializing variables in the monkeyrunner environment's 12 * namespace. During execution, the monkeyrunner program can refer to the variables "newtest" 13 * and "use_emulator" 14 * 15 */ 16 anInterpreter.set("newtest", "enabled"); 17 anInterpreter.set("use_emulator", 1); 18 19 return true; 20 }
monkeyrunner环境搭建
1.安装并配置好jdk环境
2.安装android sdk
3.安装python
4.monkeyrunner环境变量配置: {Path}Andriod_SDK ools
安装结果检测
在docs命令控制台输入命令:monkeyrunner出现如下显示内容则说明安装成功
Tips:退出monkeyrunner命令行模式可以 使用快捷键 ctrl+D退出。
小结
1.在方式二运行monkeyrunner报错(190724 14:33:20.837:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] Script terminated due to an exception)
解决方法,报出该错误是使用的notepad++编码格式问题,notepad++默认编码格式是ansi,我们使用的monkeyrunner脚本格式是utf-8,因此有冲突
修改方法如下
首先,看我们的脚本编码格式是什么,我这里的是utf-8,因此不用再做修改
3.如果编码格式不是utf-8的,就要对它进行修改了,点击格式,选择utf-8,再保存,也可选择无BOM格式的
4.再来运行一下,这次成功了
2.monkeyrunner常用的知识点
1 from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage
#引入程序所用的模块,使用别名
1 from com.android.monkeyrunner import MonkeyRunner as mr 2 from com.android.monkeyrunner import MonkeyDevice as md 3 from com.android.monkeyrunner import MonkeyImage as mi 4 #如果给导入的模块起了别名,就必须使用别名,否则会出现错误。 5 #比如连接设备或模拟器,起了以上别名后,命令应该如下: 6 device=mr.waitForConnection()
#连接到设备或模拟器
1 #参数1:超时时间,单位秒,浮点数。默认是无限期地等待。 2 #参数2:串deviceid,指定的设备名称。默认为当前设备(手机优先,比如手机通过USB线连接到PC、其次为模拟器)。 3 #默认连接: 4 device = MonkeyRunner.waitForConnection() 5 #参数连接: 6 device = MonkeyRunner.waitForConnection(1.0,'4df74b8XXXXXXX')
#向设备或模拟器安装APK
1 #以下两种方式都是对的 2 device.installPackage('E:/JAVA/monkeyrunner/Test1/ThinkDrive_new.apk') 3 device.installPackage('E:\JAVA\monkeyrunner\Test1\ThinkDrive_new.apk') 4 #参数可以为绝对路径,也可为相对路径
#卸载设备或模拟器中的APK
1 #参数为APK包名 2 device.removePackage('cn.richinfo.thinkdrive')
1 #device.startActivity(component="包名/启动Activity") 2 #以下两种都OK 3 device.startActivity(component="cn.richinfo.thinkdrive/cn.richinfo.thinkdrive.ui.activities.NavigateActivity") 4 device.startActivity(component="cn.richinfo.thinkdrive/.ui.activities.NavigateActivity")
#手机截图
1 #获取设备的屏蔽缓冲区,产生了整个显示器的屏蔽捕获。(截图) 2 result=device.takeSnapshot() 3 #返回一个MonkeyImage对象(点阵图包装),我们可以用以下命令将图保存到文件 4 result.writeToFile('E:\JAVA\monkeyrunner\Test1\Test1_001.png','png')
#暂停
1 #暂停目前正在运行的程序指定的秒数 2 #MonkeyRunner.sleep(秒数,浮点数) 3 MonkeyRunner.sleep(5)
1 #device.type('字符串') 2 device.type('hongge')
1 #锁屏后,屏幕关闭,可以用下命令唤醒 2 device.wake()
#重起手机
1 device.reboot()
#模拟滑动
1 #device.drag(X,Y,D,S) 2 #X 开始坐标 3 #Y 结束坐标 4 #D 拖动持续时间(以秒为单位),默认1.0秒 5 #S 插值点时要采取的步骤。默认值是10 6 device.drag((100,1053),(520,1053),0.1,10)
#在指定位置发送触摸事件
1 #device.touch(x,y,触摸事件类型) 2 #x,y的单位为像素 3 #触摸事件类型,请见下文中Findyou对device.press描述 4 5 device.touch(520,520,'DOWN_AND_UP')
#发送指定类型指定键码的事件
1 #device.press(参数1:键码,参数2:触摸事件类型) 2 #参数1:见android.view.KeyEvent 3 #参数2,如有TouchPressType()返回的类型-触摸事件类型,有三种。 4 #1、DOWN 发送一个DOWN事件。指定DOWN事件类型发送到设备,对应的按一个键或触摸屏幕上。 5 #2、UP 发送一个UP事件。指定UP事件类型发送到设备,对应释放一个键或从屏幕上抬起。 6 #3、DOWN_AND_UP 发送一个DOWN事件,然后一个UP事件。对应于输入键或点击屏幕。 7 以上三种事件做为press()参数或touch()参数 8 9 #按下HOME键 10 device.press('KEYCODE_HOME',MonkeyDevice.DOWN_AND_UP) 11 #按下BACK键 12 device.press('KEYCODE_BACK',MonkeyDevice.DOWN_AND_UP) 13 #按下下导航键 14 device.press('KEYCODE_DPAD_DOWN',MonkeyDevice.DOWN_AND_UP) 15 #按下上导航键 16 device.press('KEYCODE_DPAD_UP',MonkeyDevice.DOWN_AND_UP) 17 #按下OK键 18 device.press('KEYCODE_DPAD_CENTER',MonkeyDevice.DOWN_AND_UP)
3.好了时间也不早了,今天就啰嗦、水到这里吧,哈哈!晚安。好梦!!!
您的肯定就是我进步的动力。如果你感觉还不错,就请鼓励一下吧!记得点波 推荐 哦!!!(点击右边的小球即可)
个人公众号
微信群