Appium工作原理
         首先,测试脚本开始跑的时候,会通过各自平台的客户端,使用http协议与Appium服务端进行通讯, 然后Appium服务端会根据接收到的测试指令,调用对应平台的工具通知移动设备(比如安卓的uiautomator工具)需要做什么动作, 这样移动设备就能按照测试脚本的内容来运作了。
    根据之前的描述的原理,我们猜测一下,搭建测试环境需要安装些什么:
* appium环境是不是需要appium的一个安装包?
* 我们针对android进行测试我们是不是需要android本身的一个android 的sdk?
* android 这个本身就是java基础上的,我们是不是需要配置java 的jdk?
* appium是node.js开发的,他的依赖是不是就是node.js的安装包?
* 测试脚本(以Python为例)如何和appium之间进行交互呢?是不是需要一个appium-python-client的一个第三方扩展包?
* 选择一个自己熟悉的开发语言来编写测试脚本
    实际上,我们需要装好这些工具(本次暂不考虑ios端):
1. Java环境
2. AndroidSDK
3. Python的Appium客户端(第三方库)
4. node.js
5. Appium服务端(Appium官网下载)
     其他的东西差不多在官网安装好就行了,在这里想说一下AndroidSDK的一些注意事项:
     除此之外,原生的uiautomatorviewer不能获取动态页面,什么是动态页面呢?
    
比如:
         * 某个界面存在一个计时器、时钟之类的,上面显示的时间值不断在变化;
         * 某些应用首页的banner,从右到左滑过那种;
    这些页面在使用uiautomatorviewer截取时都会报错!这不是坑爹嘛。
    万幸的是,有大佬解决了这个问题,使用他的uiautomatorviewer可以抓到动态页面。放上地址:
https://github.com/512433465/autotest_helper
首先需要启动Appium服务端(无界面版):
appium -a 127.0.0.1 -p 4723 -U 127.0.0.1:7555
# 参数:
# -a 表示Appium服务端监听的服务器,一般是在本机上"127.0.0.1";
# -p 表示Appium服务端监听的端口,默认是4732;
# -U --udid 后跟手机设备的udid值,安卓设备可通过adb命令:"adb devices" 获取该值
# 注意: udid如果是真实机器的话,会是字符串的形式,模拟器则是本地端口的形式,且模拟器需要先执行"adb connect [udid]" 命令,
# 也就是说,用模拟器的话,你要自己去查你那个牌子的模拟器是默认监听在什么端口的,【网易mumu】默认是7555
from appium import webdriver
if __name__ == '__main__':
desired_caps = {}
desired_caps['platformName'] = 'Android' # 设备平台
desired_caps['platformVersion'] = '6.0.1' # Android版本
desired_caps['deviceName'] = '127.0.0.1:7555' # devicesId
desired_caps['appPackage'] = 'com.null00.warframe' # 包名
desired_caps['appActivity'] = '.activity.SplashActivity' # 启动Activity
dr = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
         在开始之前,我们需要准备好一个capabilities(在上面的代码中就是desired_caps),用来保存一些配置参数, 以便在连接appium服务端后,告诉它我们要在哪台设备上测试什么应用程序
         其中,devicesId可以通过adb命令:"adb devices"获取,一般是字符串的形式,如果你是用模拟器的话,那么 此ID就是"127.0.0.1:7555"这种,具体端口号还需要自己去官网查,网易mumu的调试端口是7555
包名和启动页的Activity可以通过adb的logcat命令获取:
1. 首先用命令清空日志: adb logcat -c
2. 启动logcat,使用命令: adb logcat ActivityManager:I *:s
3. 手机启动你要测试的程序,然后查看日志
准备好capabilities之后就可以开始创建webdriver实例来操控手机测试了。
dr = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) #创建一个WebDriver对象来控制手机,其中4723为appium服务端监听端口
# 执行上面这条代码会耗时比较久,因为Appium需要让手机启动目标程序
# 下面就可以写你的用例代码了:
dr.find_element_by_id("com.null00.warframe:id/comm_back").click()
...
Appium的定位方式基本上和Selenium相同,主要有以下几种
1. 常用定位:
* Id定位 dr.find_element_by_class("id")
* className定位 dr.find_element_by_class_name("ClassName")
* xpath定位 dr.find_element_by_xpath("xpath")
2. 层级定位:
3. List定位
4. Android uiautomator定位
常用的定位方法中,Id和ClassName定位没什么好说的,用uiautomatorviewer查找就行了,xpath定位可能会比较复杂,下图是xpath的一些基本语法:
层级定位:
         下面我们举一个简单的例子来理解层级定位:
从这张图片我们不难看出,如果我们要定位这个元素我们是没办法去定位的,这种情况我们大多数使用的是层级定位以及xpath,这里我们来看如何使用层级定位。
首先我们可以看出两幅图的结构上的区别,第二幅图元素他是在第一幅图里面的,这里我们称第一幅图id为cn.com.open.mooc:id/rv_child的节点为第二幅图元素的父节点,我们只需要先通过id定位到父节点,然后再从父节点往下面进行定位就好:
element = driver.find_element_by_id("cn.com.open.mooc:id/rv_child")
element.find_element_by_class_name("android.widget.FrameLayout").click
List 定位:
         其实就是常用定位方式的复数版:
         find_elements_by_xxx()
         此类函数会返回一个List,包含了所有符合条件的元素,如果一个都没找到,则返回空List
Android uiautomator定位:
         仅仅使用Appium提供的常用定位方式,可能不够全面,也不够强大,可能存在一些绞尽脑汁也定位不到的元素;这时如果能够使用android原生的定位方式就更好了。
         没错,Android官方也提供了定位元素的方法,它就是uiautomator,Appium提供的方法,它只是根据一些比较特别的参数来定位,比如id、classname,但uiautomator 是官方提供的,几乎可以根据所有的属性值来定位!
           放上官方文档自己感受下:https://developer.android.com/reference/android/support/test/uiautomator/UiSelector
         例如:
ele = driver.find_element_by_android_uiautomator('new UiSelector().text("请输入手机号")')
ele.send_keys("123")
注意后面的字符串,是用Java写的,还有以下几种方法:
text 模糊定位:
ele = driver.find_element_by_android_uiautomator('new UiSelector().textContains("请输入手")')
ele.send_keys("123")
resourceID 定位:
ele = driver.find_element_by_android_uiautomator('new UiSelector().resourceId("cn.com.open.mooc:id/et_phone_edit")')
ele.send_keys('234')
还有很多种定位方式,可以自行百度、谷歌搜索...
试想一下:
         当你在调试你写的用例脚本的时候,你的脚本跑到一半挂了,这时候你修改了一行代码,想先试试这行代码的表现如何,但是问题来了, 你得重新跑整个用例,想想看,使用Appium启动目标程序要多慢啊,而且在某些场景下也许重新跑用例会非常麻烦。这时候使用这个工具就方便多了————————————————Selenium_tools
Selenium_tools包含了两个工具,它们使用WebDriver创建时用于辨识实例的session_id和command_executor(相当于账号和密码)来重新连接到已经打开的实例。
这么说可能有点抽象,演示一遍吧。。。
附上地址:https://github.com/F-JH/selenium_tools