【转】管住那只猴子 — 使用RobotFramework驾驭MonkeyRunner实践

文章原地址:http://bbs.utest.qq.com/1115

一、 我们的问题是什么
在最近的项目测试中,交付的是一组基础功能库,用于手游项目快速实现登录、选区选服、支付等基础功能的对接。支持主流的Unity和Coco2dx平台。在提供库的同时,项目开发了教学版DEMO,一是用来指导用户,让用户能参考DEMO快速完成对不同功能的使用,二是利用DEMO来对每次迭代发布的版本进行测试验证。

下面几幅图是DEMO的预览:

qq%e6%88%aa%e5%9b%be20160920150743

为了实现DEMO测试的自动化,参考了Android开发环境自带的MonkeyRunner,该组件能够实现Android手机上各种点击交互操作,如“启动app”、“等待Activity出现”、“坐标点击”、“基于HierarchyViewer的控件识别点击”、“截图”、“重启手机”等。具备这些能力后基本能覆盖DEMO的自动化要求。

先看一段简单的用例脚本:

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

 

from com.android.monkeyrunner.easy import EasyMonkeyDevice

from com.android.monkeyrunner.easy import By

from com.android.chimpchat.hierarchyviewer import HierarchyViewer 

#case login-微信 

#启动程序

device.startActivity(component=’com.tencent.tmgp.apollo/com.tencent.tmgp.apollo.ApolloTest’) 

#点击login

device.touch(380, 150, MonkeyDevice.DOWN_AND_UP)

MonkeyRunner.sleep(5) 

#点击微信登陆

device.touch(500, 150, MonkeyDevice.DOWN_AND_UP)

MonkeyRunner.sleep(5) 

#点击微信确认

device.touch(500, 150, MonkeyDevice.DOWN_AND_UP)

MonkeyRunner.sleep(5) 

#截图

image=device.takeSnapshot()

#截图后比较

imageA = MonkeyRunner.loadImageFromFile(‘xx.png’,’png’)

if image.sameAs(imageA, 0.95):

    print ‘通过

else:

    print ‘失败 

……other case ……

 

 

在使用MonkeyRunner完成一些用例后,问题逐步呈现出来了,采用python编写的脚本中,多个用例顺序写下来,在使用这个脚本时会存在下面的问题

qq%e6%88%aa%e5%9b%be20160920150849

总结上面的问题就是不灵活、难维护。

二、基于关键字驱动的自动化方案

经过收集了解,在python语言下RobotFramework工具是基于关键字驱动的自动化框架,总体思路是把MonkeyRunner的底层库进行统一封装,用例中使用封装后的关键字进行步骤编写,用例则可以采用RobotFramework的可视化工具RIDE统一管理,这样上面的问题就都引刃而解了。当然实施过程有不少阻碍问题需要解决。

image005

1.   RobotFramework框架简介

RobotFramework架构是一个通用的验收测试和验收测试驱动开发的自动化测试框架(ATDD)。它具有易于使用的表格的测试数据的语法和它使用关键字驱动的测试方法。其检测能力可以通过测试库实现可以使用Python或Java的扩展,用户可以使用相同的语法,用于创建更高层次的现有的关键词。

本方案主要是封装MonkeyRunner的基础库,让原生函数更好使用。还会结合各种开源python库一起集成到Android的测试基础库中。

image006

2.   使用RF框架后在用例管理维护上的区别对比

1)   Keyword提取后的底层库封装脚本

 def SetPhoneType(self,phoneType):

 

        self.map.set_phoneType(phoneType) 

  def touchByCoordinate(self, xname, yname):

        x = self.map.coordinatemap[xname]

        y = self.map.coordinatemap[yname]

        print int(x)

        print int(y)

        device.touch(int(x),int(y), MonkeyDevice.DOWN_AND_UP)

        self.log.failed(“just want failed”) 

  def touchByCoordinateUseAdb(self, xname, yname):

        x = self.map.coordinatemap[xname]

        y = self.map.coordinatemap[yname]

        print int(x)

        print int(y)

        strTemp = ‘input tap ‘ + str(x) + ‘ ‘ + str(y)

        print strTemp

        #device.shell(‘input tap 520 1190’)

        device.shell(strTemp)

        MonkeyRunner.sleep(5)                

def snapAndSave(self,casenum):

        now = time.strftime(“%Y-%m-%d %H-%M-%S”, time.localtime())

        result = device.takeSnapshot()  

        pathok = snappath + ‘__’ + casenum + ‘__’ + str(now) + bakname

        print snappath

        print pathok

        result.writeToFile(str(pathok),’png’)

        MonkeyRunner.sleep(5)        

 def startApp(self,appID):

        device.startActivity(component= appID)

        MonkeyRunner.sleep(10)

        

2)   Keyword提取后的用例脚本

可以看到表格化的方式写用例是非常的直观,对应的用例文本是通过缩进识别的。

image007
微信正常登录

 

    plus

    verify Plus

SetPhoneType    MI3

startApp    com.tencent.tmgp.apollo/com.tencent.tmgp.apollo.ApolloTest

snapAndSave    1-2-1

touchByCoordinate    main_login_btm_x    main_login_btm_y

snapAndSave    1-2-2

touchByCoordinate    login_wechat_btm_x    login_wechat_btm_y

snapAndSave    1-2-3

touchByCoordinateUseAdb    wechat_confirm_btm_x    wechat_confirm_btm_y

snapAndSave    1-2-4

3)   改造前后的对比

 qq%e6%88%aa%e5%9b%be20160920151149

三、方案的实施和注意点

 该方案主要包括RF环境的搭建、MonkeyRunner的底层库的bug修改、java版的RF的运行脚本指定。

1.   安装RF

安装RobotFramework步骤比较简单,按下面的顺序即可,主要是有一个win64下识别不到python路径的问题需要解决。

1 python-2.7.8.amd64.msi
2 wxPython2.8-win64-unicode-2.8.12.1-py27.exe
3 robotframework-2.8.5.win-amd64.exe
4 robotframework-ride-1.3.win-amd64.exe

 

对于64位的安装包不识别python,可以复制下面的脚本,然后执行“python scriptXX.py”

import sys 

 

from _winreg import * 

# tweak as necessary

version = sys.version[:3]

installpath = sys.prefix 

regpath = “SOFTWARE\\Python\\Pythoncore\\%s\\” % (version)

installkey = “InstallPath”

pythonkey = “PythonPath”

pythonpath = “%s;%s\\Lib\\;%s\\DLLs\\” % (

    installpath, installpath, installpath

) 

def RegisterPy():

    try:

        reg = OpenKey(HKEY_CURRENT_USER, regpath)

    except EnvironmentError as e:

        try:

            reg = CreateKey(HKEY_CURRENT_USER, regpath)

            SetValue(reg, installkey, REG_SZ, installpath)

            SetValue(reg, pythonkey, REG_SZ, pythonpath)

            CloseKey(reg)

        except:

            print “*** Unable to register!”

            return

        print “— Python”, version, “is now registered!”

        return

    if (QueryValue(reg, installkey) == installpath and

        QueryValue(reg, pythonkey) == pythonpath):

        CloseKey(reg)

        print “=== Python”, version, “is already registered!”

        return

    CloseKey(reg)

    print “*** Unable to register!”

    print “*** You probably have another Python installation!” 

if __name__ == “__main__”:

    RegisterPy() 

 

安装完之后,需要设置“d:\Python27\;d:\Python27\Scripts;”这样的路径到PATH中。

2.   修复MonkeyRunner的bug

由于MonkeyRunner最初设计使用时是采用monkeyrunner.bat启动执行,在单独调用其底层库时有一个ChimpChat对象没能初始化,所以单独调用是会失败的。所以我们就需要下载源码进行修改,通过网上搜索找到了解决办法,最后我们使用新的MonkeyRunner.class去替换原版monkeyrunner.jar的class即可

编译工程中需要使用的依赖jar包可以打开原生的monkeyrunner.jar查看其META文件,得到依赖jar列表。这一点熟悉java的朋友应该会理解。

下图选中部分是优化的代码
image008
if(chimpchat == null) {

 

            Map<String, String> chimp_options = new TreeMap<String, String>();

            chimp_options.put(“backend”, “adb”);

            chimpchat = ChimpChat.getInstance(chimp_options);

            MonkeyRunner.setChimpChat(chimpchat);

        }

image009

 

3.   RF Java版的执行批处理内容

为了后续支持CI,我们采用批处理方式来启动用例执行,使用了RF的java独立版运行库robotframework-2.8.5.jar,这个jar包启动时还需要指定下面几个要素:

1 指定robotframework-2.8.5.jar路径
2 指定MonkeyRunner的各种jar包路径
3 指定抽象KeyWord的库路径
4 指定用例文件的路径

下面是批处理参考

java -cp “D:\auto-android\robotframework-2.8.5.jar”;”D:\adt-bundle-windows-x86_64-20140702\sdk\tools\lib\chimpchat.jar”;”D:\adt-bundle-windows-x86_64-20140702\sdk\tools\lib\ddmlib.jar”;”D:\adt-bundle-windows-x86_64-20140702\sdk\tools\lib\guavalib.jar”;”D:\adt-bundle-windows-x86_64-20140702\sdk\tools\lib\monkeyrunner.jar”;”D:\adt-bundle-windows-x86_64-20140702\sdk\tools\lib\sdklib.jar”:”D:\adt-bundle-windows-x86_64-20140702\sdk\tools\lib\hierarchyviewer2.jar”;”D:\adt-bundle-windows-x86_64-20140702\sdk\tools\lib\hierarchyviewer2lib.jar”;”D:\adt-bundle-windows-x86_64-20140702\sdk\tools\lib\swtmenubar.jar”;”D:\auto-android\org.eclipse.swt-3.1.jar” -Dcom.android.monkeyrunner.bindir=”D:\adt-bundle-windows-x86_64-20140702\sdk\tools” -Djava.library.path=”D:\adt-bundle-windows-x86_64-20140702\sdk\tools\lib” org.robotframework.RobotFramework –pythonpath=E:\autoDEV\robotprj\RobotTest\TestLib –loglevel=TRACE “E:\autoDEV\robotprj\RobotTest\TestSuite\calc_suite.txt”

 

四、方案实际运行原理及报告预览

image010
image011

 

五、后续计划

目前已经能实现在RIDE中进行用例编辑,通过批处理指定tag的方式来执行用例,但是还不能再RIDE中直接进行运行,不过这个问题已经在分析中了。

另外,在熟悉了RF这个框架之后,深深的被其能力给吸引,后续打算把这套Android的Keyword库在公司内开源,让更多大牛来提升这个框架在Android自动化上的能力。

posted @ 2016-10-25 16:21  lynnLi  阅读(596)  评论(0)    收藏  举报