Appium原理小结
Api接口调用selenium的接口,android底层用android的instrumentation(API2.3+ 通过绑定另外一个独立的selendroid项目来实现的)、uiautomator接口(API4.2+),ios底层用ios的uiautomation接口。
Client/ServerArchitecture
Appium server是用node.js写的,安装node.js可以直接用npm命令或dmg,server端功能:监听一个端口,接收client发送来的command,翻译这些命令,把这些command转成移动设备可以理解的形式发送给移动设备,然后移动设备执行完command后把执行结果返回给appium server,appium再把执行结果返回给client。
Client其实就是发起command的设备,一般来说就是执行代码的机器,执行appium测试代码的机器,可以把client理解成代码,这些代码可以是java、python、ruby、js,只要实现了webdriver标准协议就可以。
跨语言:只要支持selenium webdriver api和这种语言相关的client libraries就可以。Server放在任意机器上,哪怕是云服务器都可以(appium和webdriver天生适合云测试)。
Session
session就是一个会话,在webdriver/appium,你的所有工作永远都是在session start后才可以进行的。一般来说,通过POST /session这个URL,然后传入Desired Capabilities就可以开启session了。
开启session后,会返回一个全局唯一的sessionid,以后几乎所有的请求都必须带上这个session id,因为这个seesion id代表了你所打开的浏览器或者是移动设备的模拟器。
进一步思考一下,由于session id是全局唯一,那么在同一台机器上启动多个session就变成了可能,这也就是selenium gird所依赖的具体理论根据。
Desired Capabilities
Desired Capabilities携带了一些配置信息。从本质上讲,这个是key-value形式的对象。你可以理解成是java里的map,python里的字典,ruby里的hash以及js里的json对象。实际上Desired Capabilities在传输时就是json对象。
Desired Capabilities最重要的作用是告诉server本次测试的上下文。这次是要进行浏览器测试还是移动端测试?如果是移动端测试的话是测试android还是ios,如果测试android的话那么我们要测试哪个app? server的这些疑问Desired Capabilities都必须给予解答,否则server不响应,自然就无法完成移动app或者是浏览器的启动。
Appium Clients
原生的webdriver api是为web端设计的,appium官方提供了一套appium client,为不同的语言的开发者可以测试自己的app,测试的时候,一般要使用这些client库去替换原生的webdriver库。算是client对原生webdriver进行了一些移动端的扩展。
android框架
ios框架
appium0.18.x到appium1.x 的改变
1.新的客户端库
appium客户端库取代原来的webdriver客户端库
from appium import webdriver取代fromselenium import webdriver
2.新的capabilities选项
不再使用device、version,使用platformName、platformVersion、deviceName、automationName(“Selendroid”如果是api2.3以上要选择,默认可以不填),udid(ios要指定设备标示)。
之前的app这项capability保留不变,但该项现在专门用在非browser类型的app上面,要测试Safari或Chrome浏览器应用,要使用标准的browserName,app和browserName都是专用的选项。
同时我们也用骆驼命名法重新统一命名了我们的Appium Server的capabilities。比如说原来的app-package和app-wait-activity将改成appPackage和appWaitActivity。当然,鉴于我们能自动检测到Android应用的包和activity,所以你可以大多时候忽略掉这些选项了。
3. 我们把以下的控件查找器策略给移除掉了:
name
tag name
我们现在引入了accessibility_id这个策略来取代原来name所做的事情(也就是说AppiumDriver.findElementByName将会被现在的AppiumDriver.findElementByAccessibilityId取代)。当中细节将会根据你使用的Appium客户端而有所不同。
新的class name将会取代原来的tag name原来的findElementByTagName将会被想在的findElementByClassName取代,所以如果你要根据一个控件的UI类型来查找出该控件,请使用class name这个控件查找器。
注意class name和xpath策略的变化:你现在需要使用FQCN来描述你的控件。也就是说如果你由一个xpath选择子如下所述:
//table/cell/button
findElementByXpath(""//TextView[contains(@text,'Addnote')]"")
findElementByXpath("//android.widget.TextView[contains(@text,'Addnote')]"):
//UIATableView/UIATableCell/UIAButton(如此类推:button现在就要写成android.widget.Button)
同时我们也添加了如下的控件定位器策略,也就是说入Andoid增加了AppiumDriver.findElementByUiAutomator
iosuiautomation
androiduiautomator
请根据你使用的客户端(根据不同语言)库来确定如何使用新的控件定位器策略。
4.使用XML取代JSON
取得当前窗口的源码,返回的格式将从原来的JSON改成XML。所以如果你之前的代码有依赖分析控件源码的地方必须做相应的更新。
5. 混合应用通过context而非window进行支持
如今Appium支持(跟切换上下文这个概念)更加概念一致的的“context”。为了取得所有可用的上下文或者你的应用特有的上下文,请使用如下方式:
# python driver.contexts current = driver.context请使用如下方式进行切换:
# python driver.switch_to.context("WEBVIEW")6. execute_script("mobile:xxx")将销声匿迹
所有”mobile:”相关的方法讲都会被剔除掉,并且被Appium客户端库的原生方法给替代掉。例如原来的driver.execute("mobile:lock",[5])将会被现在的driver.lock(5)所取代(这里lock这个功能已经成为了原生的客户方法了)。当然,具体的调用方法将会根据你所使用的不同的客户端库而有所不同了。
需要特别声明的是,手势操作相关的方法将会被新的TouchAction/MultiAction API所替代,把这些手势操作集合在一起将会使得你的手势操作相关的自动化更强大和通俗易懂。更详细的TouchAction/MultiAction的使用请查看你的的Appium客户端。