我不能保证我在这里写下的每一句话都正确,但写在这里的每一句话都包含着我的思考和总结。是对也好,是错也好,希望大家看完后有自己的思考,那就说明您没有白看,我没有白写。探索测试的深度,享受测试的乐趣。

Android自动化测试之Monkeyrunner从零开始(三)

上一篇 / 下一篇  2013-11-17 10:41:51 / 个人分类:自动化杂谈

时光过得太快了,一晃离上一篇monkeyrunner系列的博客已经一年多了。这一年多时间经历了太多改变,一直没时间好好去总结和分享。直到今天在微博上和朋友聊到monkeyrunner,才想起趁这个机会再总结一下之前所积累的一些经验和技巧,在这里再次和大家分享下,也算是将这个从零开始系列再进一步,呵呵。  

现在说起Android端的功能自动化测试工具,其实还是蛮多的了,像很早就风靡的Robotium,后起之秀Uiautomator,跨平台的appium等,几乎从工具这个层面还是可以满足大家的要求了。MonkeyRunner作为其中的一员,其实并不能算是特别好用的一款,我平时用得就不多。因为毕竟从SL4A衍生出来,不是基于Android的直系血亲Instrumentation,天生就有运行速度慢,容易出错,可用的接口少等缺点,可谓是有点“先天不足”。当然优点还是有的,比如基于Jython语言来编写,语法简单易学,可以跨应用,可以直接以ID来操作测试,不需要签名等其他工具不具有的一些特点,所以有时也有它的用武之地,大家学习和掌握它之后应该也有一些机会是可以用到它的,紧急时候救救急啥的也还不错。  

既然Monkeyrunner先天不足,如果想要让它好用的话,那当然就只能后天补足了。前段时间在网上找到一个非常强大的monkeyrunner的第三方库wrapEasyMonkey,是基于EasyMonkeyDevice来二次封装的,并加入了自动异常处理、失败重试、case管理、断言、获取控件上的文本等,大大增强了monkeyrunner本来的功能,使得monkeyrunner强大了不止一个级别。除了运行还是比较慢这个没法解决之外,可以说其他的几乎都有了较大的改善。说句实话,原生monkeyrunner几乎没法直接使用。所以建议选用monkeyrunner作为自己的测试工具的童鞋,都可以去找找这个包来用用,确实挺好用的。具体的用法我这里就不啰嗦了,作者的教程还是写得蛮细的,相信有一定python基础的童鞋都应该看得懂。但在这里,我想重点分享的还不止这个第三方包,还有我个人对这个包的一些改进的想法。在wrapEasyMonkey的作者提供的包里,很多方法都是根据控件ID来操作的,比如getView(self,id)。但经常做Android自动化测试的朋友肯定都知道这里有个问题,很多时候我们的app里的控件要么没有ID,要么ID值就是重复的。在这种情况下,根据ID肯定是无法获取到这个控件的引用的。那么怎么办呢?我当时也是为这个问题非常地苦恼,但后来我仔细研究了Hierarchy Viewer得到的控件树形图,其实我们完全可以基于每个控件所在的子节点的位置,结合python函数的不定参数的特性,去获取任意已知ID的父节点的任意子节点的引用,然后再用这个引用作为参数去获取其对应的文本、断言等等,就方便多了,再也不会受到没有ID或者是ID重复的限制了。当然,要达到这样的功能需要修改原来那个包里的部分函数。

这里我举个实际例子来说明一下吧。假如我们现在就来测试一下Android自带的contact联系人那个app,假设我们先加上了一个联系人,现在我们用monkeyrunner来验证一下我们加入的联系人的信息是否正确。这里实际上就涉及到几个比较重要的操作:1. 获取对应的控件 2. 判断上面的文字是否和预期一致,也就是下面图上三个红色框所表示的部分。hierarchy viewer里的完整的图比较大,这里显示不了,所以大家可以自己通过这个hierarchy viewer来看看。



通过hierarchy viewer里显示的树形结构来看,这里显示电话号码158xxxxxxxx的控件和邮箱地址41420872@qq.com的控件ID都为text2,很明显,重复了。所以没法用原包里的getView(self,id)方法来获取这个view的引用。那是不是就没办法了呢?其实我们可以换个角度来看,即不从ID角度,而是从这个控件树的节点角度来思考如何获得控件的引用。我们可以看到在hierarchy viewer图中的每个控件所对应的框形中,右下角都有一个数字,如下图中红色框中的0和1所示。




其实这个数字就是该控件在同级兄弟节点中的索引值,我们知道这个索引值后,就可以根据parentView.children[index]属性来获取任意父节点所对应的子节点的对象引用。其中的parentView可以是树形图中有有效ID的任意父节点,然后利用python函数的可变参数列表特性来传入所需控件的索引列表即可构造出得到任意节点引用的字符串,从而得到其引用。核心代码如下:

def getChildView(self, parentId, *childSeq):
    hierarchyViewer = self.device.getHierarchyViewer()
    str_getchildview="hierarchyViewer.findViewById('" + parentId +"')"    
    for index in childSeq:       
        str_getchildview+=('.children[' + str(index) + ']')         
    exec 'child_view=' + str_getchildview
    return child_view

现在我们来看看这段代码如何使用。比如我们刚刚那个联系人的详细信息界面的联系人号码控件的hierarchy viewer截图如下:



联系人号码控件的对象引用可由这个语句获得:phone_number=device.getChildView('id/contact_data', 0, 0, 1, 0)。其中“contact_data”这个是其父对象的ID,这个ID必须符合两个条件,即有效和唯一。通过这个ID,我们就可以得到它的任意子孙节点的引用,0,0,1,0则是联系人控件在对象树中的索引链上的位置,大家对照着图应该很容易理解。有了这个引用之后,我们就比较好对所有以ID作为参数的方法来做改造了,你想改哪个就改哪个。这里我举个例子,比如原来wrapEasyMonkey包里有个方法是用来取得控件上的文本的getTextById(self,id),这也是我们要验证文字时所必须要用到的方法。但如上图所示,其实联系人的控件的ID是有重复的(跟邮箱地址那个控件的ID重复),我们不可能用这个重复的ID去调用getTextById方法,所以我们就只能根据刚刚我写的那个方法来先得到联系人控件的引用,再将获取文本这个方法改成根据传view的引用来获取文本。核心代码如下:

def getText(self,view):
    if view != None:        
         return (view.namedProperties.get('mText').toString().split('=')[1]).encode('utf8')

这下就要灵活很多了,就算你要获取那个对象没有ID或者ID是重复的,都不影响你的操作,因为它在对象树中的位置不可能重复,呵呵。  

好了,这次就说这么多了吧。这里我只是就我自己的一些想法和感受写一些抛砖引玉的文字,有不对的地方欢迎各位指正,当然也欢迎各位看官提出更多的想法,一起来改进我们的工具,将Android平台的自动化做得更好,呵呵。

TAG: 零基础 入门 扇门 Monkeyrunner monkeyrunner 重复ID

ransally的个人空间 引用 删除 ransally   /   2015-10-15 17:22:18
给予给看完整脚本看下吗?
引用 删除 lihongmei   /   2015-08-25 16:00:44
5
小鱼在乎的个人空间 引用 删除 小鱼在乎   /   2014-05-04 17:22:44
最近在学习monkeyrunner,但是毫无头绪,python也不是很懂。求大神们知道,如何入门,该怎么学习!
小鱼在乎的个人空间 引用 删除 小鱼在乎   /   2014-05-04 17:21:25
5
引用 删除 zhx0611   /   2014-04-28 14:29:47
这个很不错 以后可能会用上 谢谢
引用 删除 zhx0611   /   2014-04-28 14:26:18
3
引用 删除 monkeyrunner   /   2014-01-13 09:26:19
你好,楼主!根据楼主的getChildView这个方法可以找到子节点的对象,也能够找到子节点对象的内容,但对它使用touchView这个方法却不好使!谢谢楼主!
wrap touch view function
0 time touch error , not found the view , will retry
1 time touch error , not found the view , will retry

原帖由monkeyrunner于2014-01-12 17:06:29发表
你好,楼主,我刚才发现一个问题,我使用wrapeasyMonkey的getView方法获取对象以后,再使用touchV.
引用 删除 monkeyrunner   /   2014-01-12 17:06:29
你好,楼主,我刚才发现一个问题,我使用wrapeasyMonkey的getView方法获取对象以后,再使用touchView就好使,但这个时候用len(parent_node_view.children)会报错,没有子方法,昨天使用parent_node_view= hierarchy_viewer.findViewById(parentId)这个方法找到当前的节点对象,然后再找的子节点对象!
AttributeError: 'com.android.monkeyrunner.easy.By' object has no attribute 'chil
dren'
引用 删除 monkeyrunner   /   2014-01-12 16:34:49
谢谢,最近忙着做一些其他测试,最近才看到楼主的评论,这个星期主要引入了wrapeasyMonkey这个包,出现了很多错误,主要是hierarchyview和viewnode这个几包找不到,现在终于引入成功了。另外找到一些关于获取节点对象属性的方法,根据楼主提供的方法现在能够找到子节点的对象,但是wrapeasymonkey的touchview这个方法不好使了,怎么办呢?祝楼主2014年恭喜发财,新年愉快,马上幸福!wrap touch view function
0 time touch error , not found the view , will retry
1 time touch error , not found the view , will retry
原帖由qingchunjun于2013-12-23 17:00:21发表
原帖由monkeyrunner于2013-12-20 19:49:57发表
你好,我们最近也在做关于Android monkeyrunner的自动化.
我的测试人生 引用 删除 qingchunjun   /   2013-12-23 17:00:21
原帖由monkeyrunner于2013-12-20 19:49:57发表
你好,我们最近也在做关于Android monkeyrunner的自动化测试,现在可以通过坐标的形式进行自动测试,但也.

可以有问题的话可以给我在微博上留言哈
引用 删除 monkeyrunner   /   2013-12-20 19:50:00
5
引用 删除 monkeyrunner   /   2013-12-20 19:49:57
你好,我们最近也在做关于Android monkeyrunner的自动化测试,现在可以通过坐标的形式进行自动测试,但也想通过控件名称的形式进行自动测试,我下载了wrapEasyMonkey的包,但引入出现一些问题,另外关于控件树节点的方法还希望楼主能够再指导一下,谢谢楼主了,祝楼主工作顺利,身体健康,我的邮箱lyh870107@gmail.com,如果楼主有看到,希望回个信息,谢谢!
引用 删除 passerby_sec   /   2013-12-02 11:15:14
虽然用不上了,但总算弥补了心中的好奇。
以前测试都是用坐标值定位,所有界面都得手动查看,功能都得执行一遍,一直想着要是有控件控制就好了,thanks~
引用 删除 passerby_sec   /   2013-12-02 11:13:25
5
 

评分:0

我来说两句

qingchunjun

qingchunjun

十年软件测试经验,三年测试项目和团队管理经验,非典型性程序员。注重测试理论体系的研究和测试实际项目的结合。目前专注于移动平台自动化测试项目经验探索和自动化测试平台建设。同时也对python和android较感兴趣,希望和大家一起交流学习。新浪微博@pure0927

日历

« 2024-04-11  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 233211
  • 日志数: 16
  • 建立时间: 2011-01-05
  • 更新时间: 2015-01-07

RSS订阅

Open Toolbar