之前工作中接触了Appium相关自动化测试,感觉Appium涉及的技术点比较多,整体是一个比较复杂的结构。最近有时间总结了一下关于Appium的知识点。
基本介绍
Appium是一个跨平台,可以在iOS/Web/Android同时运行的自动化测试框架。同时,它支持通过各种客户端python/java/js/rubby/C#用于编写测试用例。同一套测试代码可以用在不同的平台上进行测试,减少了很多重复的工作量。
实现了端到端的测试:通过任意一门支持WD网络协议的语言客户端就可以实现对不同平台App客户端的测试。实际上因为它是基于网络构建的测试框架,所以测试设备和Appium Server 也能支持部署到云上。
好处:不需要理解和学习各个平台的测试开发技术,可以把Appium本身当做一个平台,它屏蔽了来自各原生平台的技术点。最后减少很多由于平台不同带来的额外的开发工作量。
成本:需要理解appium基本运行原理,自己搭建测试开发环境,知道如何调试以及获取控件ID。在iOS平台上针对appium使用中发生崩溃或者页面加载不出来等问题,不容易调试和解决,需要调试WDA源码。相对比较麻烦,如果不懂原生平台开发就很难解决相关问题。
在Appium之前使用原生测试框架进行测试的基本流程:
这时候需要先学习和了解原生平台的测试框架和相应的开发语言
使用Appium框架进行测试:
使用Appium只需要使用之前已经熟悉的一种语言编写测试用例,非常快速的上手。
基本原理
架构
配置参数
在启动Appium进行测试之前,需要先了解Appium的配置。Appum支持多个平台和多台设备的测试,相关的参数基本都是为了定义当前测试是针对哪些平台和具体哪个设备进行的:
platformName: 平台名称, iOS, Android
deviceName: iPhone 12
platformVersion: 15.0
device udid: 00000001-000000000000000A
bundle id: com.company.app
组成部分
Appium包含了WebDriver客户端, Appium Server, WDA(appium-uiautomator2-server / bootstrap.sh), XCUITest(UIAutomation2)
在WebDriver客户端中,包括了自己编写的测试用例代码以及支持MJWP协议的基础库,基础库支持了将测试用例代码中的方法指令,转换成实现了MJWP协议的Htttp请求。
Appium Server处理来自WebDriver客户端的请求,解析MJWP协议之后,根据参数配置按照不同的设备,不同的app进行请求的转发。
WDA是运行在特定iOS设备的服务端程序(对于android来说,是bootstrap.sh/ appium-uiautomator2-server),它用于根据Appium Server的请求,将其转换为本地测试框架(XCUITest 或者是 UIAutomation2)的测试调用。
Appium Server
Appium是支持多台设备,多个App同时进行自动化测试的,每台设备的管理都是通过Session进行的。所以对于Session的管理,处理WebDriver协议,记录运行日志等功能都需要一个公共的独立服务来处理,这样Appium Server就显得有必要了。
否则就必须在WebDriver层处理这些逻辑,但是WebDriver支持的语言有6种后面可能还会增加,每种语言都要实现重复的逻辑确实毫无必要。
Web Driver
网络协议:
WebDriver Protocol
发展历史:
最开始为了方便在Web 浏览器领域的自动化测试,W3C有一个相关的标准叫JSON Wire Protocol,后来改了名字叫WebDriver Protocol。它定义了浏览器自动化测试中的各种行为功能,比如创建一个Session,鼠标点击/拖拽事件,浏览器tab和窗口切换/关闭/打开等。
协议的具体内容可以参考文档:
Mobile JSON Wire Protocol
后来由于移动端自动化测试的需要,在WebDriver的基础上发展出了Mobile JSON Wire Protocol协议。它在原来的基础上拓展了一些功能, 比如:
1.网络连接种类: wifi / 蜂窝
2.元素定位方式: xpath / accessbility id / class name
class name : 原生平台的实现类,类似UIButton, UILable等。
Accessbility id: 控件id
Xpath: XML文件中可以根据Xpath进行定位
3.设备和app的旋转
实际运用
举个例子,比如说Click事件,它有两步:
1.需要先通过accessbilityID找到元素
2.触发元素的click事件
以java为例,在WebDriver客户端中的实现是:
MobileElement el = driver.findElementByAccessibilityId("SomeId");
el.click();
它们在Mobile JSON Wire Protocol的定义是:
//查找元素事件, url参数是session_id, JSON参数是
//using: 查找元素使用的查找策略, value: 目标对象的搜索id
POST /session/session_id/element
//点击事件:url 参数是session id 和 element_id
POST /session/{session id}/element/{element id}/click
实际上,Java编写的测试代码最后会被WebDriver转换成符合MJWP协议的请求。
在WebDriver客户端中涉及WebDriver协议的部分可以参考:WebDriver FindElement,但是我发现具体的方法名是没有明确定义的,在不同的语言中名称也不同。可能主要是参考为主,明确功能就可以了。
在Appium中WebDriver协议的具体应用可以参考:Appium FindElement
Web Driver 客户端
Web Driver客户端通过给WDA发送满足MJWP网络协议的请求,来驱动WDA进行测试。因为它是基于网络通讯的,所以基本上客户端语言没有什么限制,主要支持MJWP协议即可。
一般测试编写的开发测试脚本客户端都是基于某种语言的webDriver进行开发的,WebDriver封装了常用的测试命令以及发送请求给WDA。所以一般开发测试脚本之前,需要先安装好对应语言WebDriver基础库。
如果现在需要对一门新语言进行支持,让它可以使用Appium进行自动化测试。首先需要有一个对应的Web Driver库。
控件ID: AccessbilityId
控件ID定义了一段文本或者一个按钮唯一识别标识,XCUITest通过控件ID查找控件,然后实施点击的测试测试。
控件ID 定义规则,举个例子:
"Prefix_" + "ClassType_" + "Text"
//比如
Prefix_UIButton_按钮
Prefix_UILable_名称
Prefix是前缀,ClassType是当前元素对应的基本类型,Text是当前元素展示的文本信息
WDA
在iOS平台,WDA是WebDriverAgent的缩写,它本身是一个基于原生平台对Appium Server 提供的服务。用来解析测试命令和参数,以及驱动原生平台自动化测试框架进行测试和获取元素。在不同的平台上,都有对应类似WDA的服务,iOS在Appium 应用程序包里都自带了。
安卓之前对应的组件应该是bootstrap.sh,一个使用java编写的中间件服务,它会在测试的时候注入到设备上,以一个socket服务的方式存在设备中。最新版本换了技术方案变成了appium-uiautomator2-server,它会在开启测试的时候作为一个apk安装到设备上。
WDA iOS使用的两个核心三方库
Http服务器:
- CocoaHTTPServer
请求路由处理:
- RoutingHTTPServer
1.测试命令请求:命令都包含在请求Url的path中
页面的View层级信息:
//通过XML的格式返回
"/PageSource"
各种点击事件:
//点击
"/element/:uuid/click"
//滑动
"/wda/element/:uuid/scroll"
//双击
"/wda/element/:uuid/doubleTap"
如何支持跨平台
各原生平台都有自己的测试框架,比如iOS是 XCUITest, android是UIAutomator2
最终Appium会通过WDA去使用原生测试框架去进行自动化测试
如何支持多语言编写脚本
因为脚本客户端是通过网络协议和Appium Server交互的,所以自然隔绝了客户端语言,只要客户端语言支持MJWP协议的http请求,都可以发送测试命令给Appium Server处理,重点是需要一个对应的Web Driver。
现在官方能支持的语言有下面这些,一共支持6种语言:
| Language/Framework | Github Repo |
|---|---|
| Ruby | github.com/appium/ruby…, github.com/appium/ruby… |
| Python | github.com/appium/pyth… |
| Java | github.com/appium/java… |
| C# (.NET) | github.com/appium/appi… |
| JavaScript (Node.js) | github.com/webdriverio… |
| JavaScript (Browser) | github.com/projectxyzi… |
| RobotFramework | github.com/serhatbolsu… |
用到的一些工具
//安装libimobiledevice
brew install libimobiledevice
//显示当前所连接设备的udid,查看设备信息
idevice_id -l
//按装ideviceinstaller
brew install ideviceinstaller
//查看设备安装的第三方应用,可以用于查看app的bundle id
ideviceinstaller -u [udid] -l
欢迎关注我的公众号
里面有更多其他文章,新文章也会第一时间发布到公众号