Android测试工具及Appium介绍Appium是C/S架构,支持Android/iOSNative、Hybrid和MobileWebApps测试框架,通过SelenumWebdriver协议与测试程序通信.Webdriver的优点是通过HTTPRPC调用Server上的进程,测试脚本的编写不受语言限制。无论是Python、Java还是NodeJS,编写测试都很容易。在本文中,将使用Python进行编程。起因是市场部同事抛出如下需求:批量添加一些微信好友。直接抓replay请求的方式是不靠谱的。微信与服务器的通信是加密的,Pass。考虑使用xposed等frameworkhook相关函数进行操作。但是xposed需要越狱,开发复杂,Pass。后来想到用UI测试工具进行模拟操作,开发起来比较简单。AndroidUI测试工具有很多,如Monkey、UIAutomator、Selendroid、Robotium等,其中UIAutomator、Monkey、Selendroid都是非侵入式UI测试,即不需要修改源码,只要安装了目标程序就可以进行测试。Robotium需要和源码一起编译测试。Appium其实是一个测试工具的统一调度软件,它集成了不同的非侵入式测试工具,对外提供统一的API。Android2.3之前的版本Appium会调用Selendroid,之后的版本直接使用UIAutomator,iOS下使用UIAutomation。Appium还支持FirefoxOS的UI测试。安装Appium官网给出了命令行下的安装方法。但实际上Appium有GUI版本,更适合在Windows/MacOS下使用。Windows下需要安装.NETFramework。>brewinstallnode#getnode.js>npminstall-gappium#getappium>npminstallwd#getappiumclient>appiumstartappium>nodeyour-appium-test.jsAppium需要依赖AndroidSDK来编译两个插件运行在手机端,所以需要先安装对应的AndroidSDK版本。这里直接使用AndroidStudio自带的SDKManager。在SDKManager中选择测试机对应的SDKPlatform和较新的Build-tools。如果需要使用模拟器进行测试,还必须安装相应的ARM/x86SystemImage和IntelHAXMInstaller来加速x86虚拟机。Appium使用adb与目标机进行通信,因此在真机和模拟器上的操作几乎是一样的,这里不再赘述如何搭建模拟器。安装完成后,需要在AppiumGUI中配置AndroidSDK目录,然后选择Android,点击Launch启动AppiumServer。AppiumServer默认监听http://localhost:4723进行RPC通信。现在我们可以打开熟悉的编程环境,编写UI测试用例了。这里是用Python写的,需要先安装Appium的PythonClient,然后在python中使用appium.webclient连接Appium服务器。pipinstallAppium-Python-Client使用Appium进行UI控制。根据注释修改相应的属性后,即可运行测试。手机需要开启adb调试。执行以下代码后,Appium会在手机上安装AppiumSettings和Unlock,然后微信就会启动。fromappiumimportwebdriverdesired_caps={}desired_caps['platformName']='Android'#测试平台desired_caps['platformVersion']='5.1'#平台版本desired_caps['deviceName']='m3_note'#设备名称,多个设备时需要区分desired_caps['appPackage']='com.tencent.mm'#apppackagenamedesired_caps['appActivity']='.ui.LauncherUI'#appdefaultActivitydr=webdriver.Remote('http://localhost:4723/wd/hub',desired_caps)#StartRemoteRPCSelenumWebdriver使用类似于JS中DOM模型的方法来选择页面中的元素。dr是当前活动的activity对象,可以使用findElementByXXX方法获取Activity中的元素。所有在Element之后带s的函数获取所有匹配的元素,不带s的函数获取第一个匹配的元素。查询函数1.findElement(s)ByName在Android中基本没用。AndroidUI没有名称属性。据说可以使用文本值获取。但是我没有成功2.findElement(s)ByClassName通过类名获取元素,用法如下:item_list=dr.find_elements_by_class_name("android.widget.LinearLayout")item_list[2].click()3.findElementById通过resource_id获取元素,在每个Activity中唯一,用法如下t=dr.find_element_by_id("com.tencent.mm:id/f7")t.send_keys(wechatId)4.AndroidAccessibilityID上的findElement(s)ByAccessbiltiyId其实就是contentDescription。设置该属性是为了方便视障人士使用手机。启用TTS后,系统会读取相关控件的contentDescription。5.findElement(s)ByXPath通过XMLPath描述查找元素。没弄成功,可能是XPath写的有问题。s=dr.find_element_by_xpath("//android.widget.TextView[contains(@text,'Search')]")s.click()6.findElementByAndroidUIAutomator通过UIAutomator的选择器获取元素。因为Appium其实是调用了Android上的UIAutomator,所以可以通过UIAutomator的selector来选择元素。el=dr.find_element_by_android_ui_automator("newUiSelector().text(\"Search\")")el.click()操作函数operation函数是用来操作选中元素的,有很多,下面只列出几个,更多请查阅手册。点击send_keys清除查询函数返回的元素对象可以像JS中的dom元素一样继续使用查询函数选择其子元素。用例如下。search=dr.find_element_by_id("com.tencent.mm:id/aqw").find_element_by_class_name("android.widget.RelativeLayout")search.click()查询规则的确定方法理解了相关函数后,下面应该是在UIPositioned上执行。如果是自己团队开发的程序,建议开发者在所有空间都加上resource_id进行绝对定位。如果遇到没有讨价还价的resource_id的元素,就需要使用其他方法定位。1、UIAutomatorViewerUIAutomatorViewer是Android官方提供的UI定位工具,位于sdk/tools下。运行后,查看器界面将打开。点击Get按钮获取当前运行的Activity的UI结构。2、AppiumDrivergetPageSourceAppiumDriver(Client)可以方便的获取当前运行的Activity的UI描述,然后根据返回的XML文档查找元素。printdr.page_source确定元素位置后,就可以按照前面提到的Find方法查找/选择元素,编写完整的测试代码。正确获取元素后,就可以获取元素相关的信息,然后使用各个语言常用的测试框架来编写测试,比如Java的JUnit,Nodejs的Mocha等。这里我主要是用Appium来模拟用户点击添加微信好友,所以完整的程序没有使用测试框架。相关UI元素获取/操作方法供您参考。#coding:utf-8fromappiumimportwebdriverfromtimeimportsleepdefaddFriend(dr,id,dryRun=False):succ=FalsewechatId=str(id)dr.find_element_by_accessibility_id(r"更多功能按键").click()item_list=dr.find_elements_by_class_name("android.widget.LinearLayout")try:item_list[2].click()except:print"Error!initemlistlen"returnssuccel=dr.find_element_by_class_name("android.widget.ListView")item_list=el.find_elements_by_class_name("android.widget.LinearLayout")try:item_list[1].click()except:print"Error!initemlistlen"returnsucct=dr.find_element_by_id("com.tencent.mm:id/f7")t.send_keys(wechatId)search=dr.find_element_by_id("com.tencent.mm:id/aqw").find_element_by_class_name("android.widget.RelativeLayout")search.click()try:freq=dr.find_element_by_id('com.tencent.mm:id/aqq')assertfreq.text==u"操作过于视频繁,请帖后再试。"print"Frequencytoohigh!Sleep300s"sleep(60)returnssuccexcept:passtry:dr.find_element_by_id('com.tencent.mm:id/a8x').click()addBtn=dr.find_element_by_id('com.tencent.mm:id/eu')ifnotdryRun:addBtn.click()succ=Trueprint"SuccessSendRequests:"+wechatIdexcept:print"NoSuchUserOrAlreadyaFriend:"+wechatIdwhileTrue:try:dr.find_element_by_id('com.tencent.mm:id/fb').click()除了:try:dr.find_element_by_id('com.tencent.mm:id/f4').click()except:breakreturnTruedefresetActivity(dr,desired_caps):dr.start_activity(desired_caps['appPackage'],desired_caps['appActivity'])desired_caps={}desired_caps['platformName']='Android'desired_caps['platformVersion']='5.1'desired_caps['deviceName']='m3_note'desired_caps['appPackage']='com.tencent.mm'desired_caps['appActivity']='.ui.LauncherUI'print"Tryingconnecttophone..."dr={}try:dr=webdriver.Remote('http://localhost:4723/wd/hub',desired_caps)exceptException,e:打印“无法连接到phone:",eexit()print"成功连接手机。"print"读取好友列表..."friendList=[]fp=open("friends.txt")line=fp.readline().strip()whileline:friendList.append(line)line=fp.readline().strip()print"读完friends.Total:"+str(len(friendList))print"等待微信splashscreen...."foriinrange(0,10):print10-isleep(1)succ_list=[]fail_list=[]foriinfriendList:try:succ=addFriend(dr,i,dryRun=False)ifsucc:succ_list.append(i)else:fail_list.append(i)except:fail_list.append(i)resetActivity(dr,desired_caps)print"SucceedList:"print"\n".join(succ_list)print"FailedList:"print"\n".join(fail_list)dr.close()【小编??推荐】AndroidUI测试框架zinc30AndroidUI的AndroidLayoutXML属性一网打尽,AndroidUI控件合集,直接拿来用!10个实用的AndroidUI工具AndroidUI线程和非UI线程
