三、MonkeyRunner复杂的功能开始学习
(1)获取APK文件中ID的两种方式
Monkeyrunner的环境已经搭建完成,现在对Monkeyrunner做一个简介。
Monkeyrunner工具提供了一套API让用户/测试人员来调用,调用这些api可以控制一个Android设备或模拟器,而不需要了解对应的源码。
有了Monkeyrunner,我们可以编写python脚本来控制apk包的安装和卸载、启动app、向app发送各种动作事件、截取图片并保存。
除此之外,MonkeyRunner是Google提供的一个基于坐标点的Android黑盒自动化测试工具。所以,要使用Monkeyrunner进行自动化测试,首先,要了解Monkeyrunner中获取坐标点的方式。

本文中,我们主要介绍两种获取坐标点的方式。一种是通过MonkeyRecorder获取坐标;另一种是通过HierarchyViewer工具获取控件ID。

一、控件坐标获取
1.Pointer location获取坐标
先说一个比较简单的获取坐标的方式,是通过模拟器中的设置-开发者选项,找到“指针位置”的选项,勾选上。如下图所示。

勾选后,模拟器的最顶部则显示坐标,比如点击模拟器上的任一应用,最顶部显示X、Y的值即该应用的坐标;同理,如果想要获取任一应用中的任一位置的坐标,也可用此方法。

  1. MonkeyRecorder获取坐标
    下面就MonkeyRecorder获取坐标的方式,进行演示。MonkeyRecorder是一个比较好用的获取坐标的工具,它是用来获取真机或模拟器上坐标的工具,当我们点击真机或模拟器上的空间时,就能显示真机或模拟器上的点击点的坐标。

(1)MonkeyRecorder的启动
首先安卓手机连接上电脑,并保证以下两个条件成立:
a.终端USB调成开发者模式
b.电脑安装手机驱动
手机连接成功后,打开cmd窗口,输入adb devices查看已连接真机或模拟器设备的名称,我们这里仍以模拟器为代表。
之后,在cmd窗口,输入monkeyrunner后,启动Monkeyrunner。做以下操作:导入MonkeyRecorder包、连接模拟器设备、以MonkeyRecorder方式启动模拟器,并依次输入
如下命令:

from com.android.monkeyrunner import MonkeyRunner,MonkeyDevicefrom com.android.monkeyrunner.recorder import MonkeyRecorder as recorderdevice=MonkeyRunner.waitForConnection()recorder.start(device)

到此,MonkeyRecorder正式启动。截图如下。

2)MonkeyRecorder的使用
我们这里只是使用MonkeyRecorder来记录坐标,获取坐标的方式很简单。比如qq的登录界面,点击“登录”按钮,右侧就会显示该按钮的坐标;同样,点击账号输入框或密码输入框,右侧同样会显示坐标。这个坐标就是我们需要获得的坐标。

同时,MonkeyRecorder中的界面是同模拟器页面保持一致的,在MonkeyRecorder中触发任一操作,模拟器上会有相应的触发。如果两者没有保持一致,则点击MonkeyRecorder右上角的Refresh Display即可刷新页面。

3.控件坐标之Monkeyrunner脚本演示
我们将下面一段Monkeyrunner脚本写到一个test.py文件中,然后运行test.py文件,查看模拟器或真机上是不是做相应的操作。

from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice device=MonkeyRunner.waitForConnection() #启动activity(这里启动qq)device.startActivity(component="com.tencent.mobileqq/.activity.SplashActivity")#登录界面,点击账号输入框device.touch(60,300,'DOWN_AND_UP') #输入qq账号device.type('3469191693')

二、控件ID获取
通过控件ID实现自动化脚本的运行,就性能而言,会比控件坐标的实现差一些;但是对于不同分辨率的设备都通用,不需要动态变换坐标。控件ID的获取主要是通过HierarchyViewer。下面就HierarchyViewer从打开方式和使用两方面进行讲解。
1.HierarchyViewer的打开方式
HierarchyViewer的打开方式有两种:一种是eclipse中打开HierarchyView视图,另外一种是命令行中执行sdk/tools/hierarchyviewer.bat。
HierarchyViewer默认只能在非加密设备使用,例如工程机,工程平板或者模拟器。如果要在手机上使用HierarchyViewer,你需要在你的应用中添加一个开源库View Server。链接地址:https://github.com/romainguy/ViewServer。该篇文章中有讲解如何启动真机View Server,大家如果有兴趣,可参考:https://dup2.org/node/1538。
方式一:连接您的真机设备,或打开模拟器,在eclipse中, 依次选择Window-Open Perspective-Other,在Other中,选择HierarchyView视图,即可打开。

方式二:连接您的真机设备或打开模拟器,运行cmd窗口,进入到sdk/tools目录下,输入命令hierarchyviewer.bat,运行hierarchyviewer。

或者直接在sdk/tools目录下,找到hierarchyviewer.bat,双击运行。

下面讲解利用HierarchyViewer获取控件ID的方法。
2.HierarchyViewer获取控件ID
HierarchyViewer启动后,首先会看到的第一个窗口显示了设备和模拟器的列表。点击左边的箭头,就会展开当前设备或模拟器的Activity对象列表。列表中显示了设备或模拟器上,UI当前可视的所有Activity对象。这些对象按照它们的Android组件名称列出来。列表中的内容包含应用的Activity对象和系统的Activity对象。
当模拟器activity画面变更后,点击refresh可以加载新的页面布局信息。

从列表中选择你的activity名称,双击,或点击菜单栏的Load View Hierarchy按钮,进入View Hierarchy窗口,查看它的view层次结构;或者点击Inspect Screenshot按钮,进入Pixel Perfect窗口,从而查看UI的一个放大图像。我们这里点击进入View Hierarchy窗口。
可以从下图中看到模拟器此activity的画面布局信息,左边部分是hierarchy通过树形结构展示的布局形式,右下角是模拟器上当前页面的UI布局信息。

通过滚动鼠标,可以放大每个树节点;拖拽鼠标,移动树形结构布局。双击树节点可以展示单独的UI部分。从下图中,可以看到,id/btn_login即为登录按钮的ID。依次类推,可以查看其它控件ID。
注:对于列表、或者弹出框则无法直接通过点击ID操作成功,需要计算ID的坐标

(2)Monkeyrunner之控件ID不存在或重复
我们在用monkeyrunner进行Android自动化时,通过获取坐标点或控件ID进行一系列操作。由于使用坐标点时,屏幕分辨率一旦更改,则代码中用到坐标的地方都要修改,这样导致代码的复用率较低。因此,我们多采用控件ID操作(注:控件ID需要在模拟器中使用,对于绝大多数真机不适用)。
但是,某些控件的ID是不存在的或重复存在,那么,遇到这种情况,我们怎样继续使用控件ID进行自动化测呢?
例如,下图中,我想要获取最右侧红框中的id/tv,但是,大家会发现,和它并列的也有重复的控件id值。现在我们就讲述一下这种情况(控件ID不存在同样处理)。

我们从这个控件树的节点角度来思考如何获得控件的引用。我们可以看到在上图hierarchy viewer中的每个控件所对应的框形中,右下角都有一个数字。其实这个数字就是该控件在同级兄弟节点中的索引值,我们知道这个索引值后,就可以根据parentView.children[index]属性来获取任意父节点所对应的子节点的对象引用。其中的parentView可以是树形图中有效ID的任意父节点(父节点要保证唯一有效),然后利用python函数的可变参数列表特性来传入所需控件的索引列表即可构造出得到任意节点引用的字符串,从而得到其引用。
核心代码如下,把如下代码加入自己的python脚本中,直接调用该函数即可。

#定义获取重复或不存在控件id,寻找子节点函数
def getChildView(parentId, *childSeq):hierarchyViewer = device.getHierarchyViewer()childView="hierarchyViewer.findViewById('" + parentId +"')"for index in childSeq:childView += ('.children[' + str(index) + ']')print childViewreturn eval(childView) #获取id的文本
def getText(view):  if view != None:           return (view.namedProperties.get('text:mText').value)

有了以上代码之后,我们可以获取上图中的id/tv,方法如下:
getChildView(‘id/province_list’,5,0,0)
其中结合上图可知,getChildView的第一个参数即:有效且唯一的父节点
参数二、三依次为要获取的控件ID的父节点的父节点
注:用到的父节点即图中的id/province_list,有效且唯一的值。当前的父节点右下角的角标,不需要在getChildView函数中显示。
这样,通过以上函数,再结合Hierarchyviewer图形,我们获取到了重复的控件ID。
由于Hierarchyviewer看起来不是特别方便,这里再推荐一款和Hierarchyviewer类似功能的工具:uiautomatorviewer(存储在sdk\tools中,双击打开即可)

由上图中,uiautomatorviewer每个控件前面的数字即相当于Hierarchyviewer的角标,我们同样可以获取到目标ID的最终有效且唯一的父节点,从而调用函数getChildView(‘id/province_list’,5,0,0)
获取到了不存在或重复的控件ID后,我们可以通过其坐标,进行点击操作。
首先,定义一个“获取指定按钮坐标”的函数

def getBtnPoint(btn):print btnpoint = device.getHierarchyViewer().getAbsoluteCenterOfView(btn);return point

然后通过坐标,实现点击操作,例如:

askView = getChildView('id/tabs',1)
askPpoint = getBtnPoint(askView)
device.touch(askPpoint.x,askPpoint.y,'DOWN_AND_UP')

到这里,我们介绍完了处理控件ID不存在或重复时的方法,自己实践一把,就会更能体会

Hierarchyviewer/uiautomatorviewer+getChildView()获取不存在或重复控件ID的用法。

(3)录制脚本与回放脚本

录制脚本,recorder.py:
01.from com.android.monkeyrunner import MonkeyRunner as mr
02.from com.android.monkeyrunner.recorder import MonkeyRecorder as recorder
03.device = mr.waitForConnection()
04.recorder.start(device)
回放脚本,recorder_playback.py:
01.import sys
02.from com.android.monkeyrunner import MonkeyRunner
03.CMD_MAP = {
04.    'TOUCH': lambda dev, arg: dev.touch(**arg),
05.    'DRAG': lambda dev, arg: dev.drag(**arg),
06.    'PRESS': lambda dev, arg: dev.press(**arg),
07.    'TYPE': lambda dev, arg: dev.type(**arg),
08.    'WAIT': lambda dev, arg: MonkeyRunner.sleep(**arg)
09.    }
10.
11.# Process a single file for the specified device.
12.def process_file(fp, device):
13.    for line in fp:
14.        (cmd, rest) = line.split('|')
15.        try:
16.            # Parse the pydict
17.            rest = eval(rest)
18.        except:
19.            print 'unable to parse options'
20.            continue
21.
22.        if cmd not in CMD_MAP:
23.            print 'unknown command: ' + cmd
24.            continue
25.
26.        CMD_MAP[cmd](device, rest)
27.
28.
29.def main():
30.    file = sys.argv[1]
31.    fp = open(file, 'r')
32.
33.    device = MonkeyRunner.waitForConnection()
34.
35.    process_file(fp, device)
36.    fp.close();
37.
38.if __name__ == '__main__':
39.    main()

录制操作:
在cmd下输入monkeyrunner recorder.py,将打开下面的窗口,该窗口的功能:
1、可以自动显示手机当前的界面
2、自动刷新手机的最新状态
3、点击手机界面即可对手机进行操作,同时会反应到真机,而且会在右侧插入操作脚本
4:、wait: 用来插入下一次操作的时间间隔,点击后即可设置时间,单位是秒
Press a Button:用来确定需要点击的按钮,包括menu、home、search,以及对按钮的press、down、up属性
Type Something:用来输入内容到输入框
Fling:用来进行拖动操作,可以向上、下、左、右,以及操作的范围
Export Actions:用来导出脚本
Refresh Display:用来刷新手机界面,估计只有在断开手机后,重新连接时才会用到

5.在左侧手机视图上做的任何操作,在右侧都会进行脚本录制
上述实例录制的操作脚本如下:
TOUCH|{‘x’:187,‘y’:356,‘type’:‘downAndUp’,}
PRESS|{‘name’:‘MENU’,‘type’:‘downAndUp’,
WAIT|{‘seconds’:5.0,}
DRAG|{‘start’:(192,128),‘end’:(192,640),‘duration’:1.0,‘steps’:10,}

回放操作:
回放:使用命令monkeyrunner recorder_playback.py record_test.py,其中record_test.py中是我们录制的脚本,这里需要使用绝对路径,即回放脚本和录制操作脚本都必须在Monkeyrunner.bat所在目录。
PS: 录制后的脚本可以进行二次更改,而且每一步操作需要有时间间隔,以保证测试的正确性

(4)MonkeyRunner常用事件

这里给大家罗列下Monkeyrunner的常用事件,基本上这些事件都能够满足我们日常写用例的需求了。

#monkeyrunner导入模块from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage#monkeyrunner连接设备device = MonkeyRunner.waitForConnection()
if not device:
print "Please connect a device to start!"
else:
print "Start "
#monkeyrunner启动一个ActivitycomponentName="com.ss.android.article.news/.activity.SplashActivity"device.startActivity(component=componentName)#monkeyrunner按键发送指定键的关键事件:  device.press(参数1:键码, 参数2:触摸事件类型)参数1:常用键内容按下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_DPAD_LEFT', MonkeyDevice.DOWN_AND_UP)按下右导航键 device.press('KEYCODE_DPAD_RIGHT', MonkeyDevice.DOWN_AND_UP)相应的按键对应名称:menu键:KEYCODE_MENUhome键:KEYCODE_HOMEback键:KEYCODE_BACKsearch键:KEYCODE_SEARCHcall键:KEYCODE_CALLend键:KEYCODE_ENDCALL上音量键:KEYCODE_VOLUME_UP下音量键:KEYCODE_VOLUME_DOWNpower键:KEYCODE_POWERcamera键:KEYCODE_CAMERA#monkeyrunner卸载包device.removePackage ('com.example.android.notepad')print ('卸载成功')#monkeyrunner安装包device.installPackage('ApiDemos.apk')
print ('安装成功')#monkeyrunner单击控件方式1:device.touch(507,72,"DOWN_AND_UP")方式2:easy_device.touch(By.id('id/qingchu'),device.DOWN_AND_UP)用后者需要导入from com.android.chimpchat.hierarchyviewer import HierarchyViewer #根据ID找到ViewNode,对viewnode的一些操作等from com.android.monkeyrunner.easy import EasyMonkeyDevice  #提供了根据ID进行访问方法touch、drag等from com.android.monkeyrunner.easy import By    #根据ID返回PyObject的方法from com.android.hierarchyviewerlib.models import ViewNode as vn #代表一个控件,可获取控件属性#monkeyrunner长按控件方式1:device.touch(507,72,"DOWN_AND_UP")device.touch(507,72,MonkeyDevice.DOWN)MonkeyRunner.sleep(1)
device.touch(507,72,MonkeyDevice.UP)
方式2:
easy_device.touch(By.id('id/qingchu'),,MonkeyDevice.DOWN)
MonkeyRunner.sleep(1)easy_device.touch(By.id('id/qingchu'),MonkeyDevice.UP)用后者需要导入from com.android.chimpchat.hierarchyviewer import HierarchyViewer #根据ID找到ViewNode,对viewnode的一些操作等from com.android.monkeyrunner.easy import EasyMonkeyDevice  #提供了根据ID进行访问方法touch、drag等from com.android.monkeyrunner.easy import By    #根据ID返回PyObject的方法from com.android.hierarchyviewerlib.models import ViewNode as vn #代表一个控件,可获取控件属性#monkeyrunner滑动屏幕for i in range(1,70):device.drag((250,110),(250,850),0.1,10)MonkeyRunner.sleep(1)#monkeyrunner延时MonkeyRunner.sleep(3)#monkeyrunner截图result = device.takeSnapshot()result.writeToFile('C:\\Users\\Martin\\Desktop\\test.png','png')#monkeyrunner截图对比result1.sameAs(result0,1.0)#monkeyrunner局部图片(前两个值是左上角左边,后两个值是右下角减左上角的坐标。)pic0= result0.getSubImage((4,41,400,700))#monkeyrunner重启设备device.reboot()#monkeyrunner单击电源键,熄灭屏幕device.press('KEYCODE_POWER',MonkeyDevice.DOWN_AND_UP)#monkeyrunner唤醒屏幕device.wake()#monkeyrunner输入文本Cotent='1234'device.type(Cotent)

史上最全的MonkeyRunner自动化测试从入门到精通(10)相关推荐

  1. 史上最全的MonkeyRunner自动化测试从入门到精通(1)

    史上最全的MonkeyRunner自动化测试从入门到精通(1) 史上最全的MonkeyRunner自动化测试从入门到精通(2) 史上最全的MonkeyRunner自动化测试从入门到精通(3) 史上最全 ...

  2. 【Github教程】史上最全github用法:github入门到精通

    原文 http://www.eoeandroid.com/thread-274556-1-1.html [初识Github] 首先让我们大家一起喊一句"Hello Github". ...

  3. 史上最详细python学习路线-从入门到精通,只需5个月时间

    针对Python的初学者,从无到有的Python语言如何入门,主要包括了:Python的简介,如何下载Python,如何安装Python,如何使用终端.Shell,IDE等各种开发环境进行Python ...

  4. python入门到精通需要学多久-史上最详细python学习路线-从入门到精通,只需5个月时间...

    针对Python的初学者,从无到有的Python语言如何入门,主要包括了:Python的简介,如何下载Python,如何安装Python,如何使用终端.Shell,IDE等各种开发环境进行Python ...

  5. python入门只需20分钟-史上最详细python学习路线-从入门到精通,只需5个月时间...

    针对Python的初学者,从无到有的Python语言如何入门,主要包括了:Python的简介,如何下载Python,如何安装Python,如何使用终端.Shell,IDE等各种开发环境进行Python ...

  6. python 需要多久能够学精通_python入门到精通需要学多久-史上最详细python学习路线-从入门到精通,只需5个月时间...

    针对Python的初学者,从无到有的Python语言如何入门,主要包括了:Python的简介,如何下载Python,如何安装Python,如何使用终端.Shell,IDE等各种开发环境进行Python ...

  7. 手把手教你新建一个winform项目(史上最全)

    文章目录 前言: 第1步.打开Microsoft Visual Studio(简称vs),本人这里使用的是Visual Studio 2017 专业版,如下图: 1.2 Visual Studio C ...

  8. python bool 转vc int_史上最全的 Python 3 类型转换指南

    史上最全的 Python 3 类型转换指南-1.jpg (13.76 KB, 下载次数: 0) 2018-8-21 17:35 上传 int 支持转换为 int 类型的,仅有 float.str.by ...

  9. HR面试题(史上最全、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

最新文章

  1. 存储的学习:freenas使用记录
  2. AngularJS优缺点、使用场景
  3. iframe cross domain
  4. 向 mysql导入数据 源码_MySQL 导入数据
  5. Oracle(二):查询、函数、集合运算
  6. synchronized基础
  7. fork 与 vfork
  8. 修复Git打包的一个Bug
  9. 华硕幻16、酷睿12代、windows11、vmware折腾总结
  10. hua图软件 mac_10款Mac上设计师必备的设计绘图工具推荐和下载 | 玩转苹果
  11. tftp命令怎么传输文件,5步掌握tftp命令的使用方法
  12. 利用selenium框架爬取京东省市区数据时,网页里面内嵌的一个窗口遇到的NoSuchElementException的 bug,原因是iframe
  13. delphi的时间Ttime,Tdatetime的信息
  14. agx 安装ros opencv_CARLA与Autoware和ROS的联合仿真安装过程
  15. 5-网站日志分析案例项目回顾与点击流数据分析项目介绍
  16. 计算机不识别u盘什么原因,电脑不识别u盘怎么回事
  17. openfoam前处理:并行计算decomposeParDict和setFieldsDict
  18. Pipeline流水线及分布式流水线发布PHP项目及JAVA项目
  19. SSM项目基本配置文件(附图)
  20. 计算机毕业设计(附源码)python自助旅游平台

热门文章

  1. Java实现阿里云视频点播的功能
  2. 强强联合,一份最适合你的后端面试指南,最终5轮面试拿下阿里Java岗Offer(定薪45K),确定不心动?
  3. 模拟登陆微博 主函数中输入自己微博的账号和密码 User-Agent也要改
  4. Labeled LDA(有监督)主题模型的理解、推理与编程
  5. CentOS -OpenStack-pike 服务搭建
  6. java和vue车辆管理系统车管所系统
  7. 东莞横沥潇洒职业培训学校丹丹老师分享避免因模具设计不良而使制品出现不均匀收缩
  8. 16012009徐小东_考核二
  9. java什么是guava_Guava教程
  10. 志强系列的服务器能吃鸡吗,国产高端 浪潮四路四核服务器产品解析