Appium iOS 自动化测试总结

一、iOS Appium 原理

1.1 iOS 9.3 系统之前自动化测试

Appium iOS 自动化测试总结_第1张图片

1.1.1 Native 自动化

这是iOS 9.3 系统之前自动化测试的架构模式。通过Android Appium 原理的学习 ,我们很容易理解 iOS Appium 原理:

  • Appium Client 端执行代码发送到 Appium Server端(Server 集成了苹果官方的 Instruments);

  • Server 端将一行行代码翻译成一条条指令,同时在手机上注入 bootstrap.jar ;

  • Server 与该 jar 包通信将指令传给 bootstrap.jar,jar 包调用手机里的自动化测试框架(UIAutomation),UIAutomation框架执行指令。

1.1.2 Hybrid(WebView)自动化

通过 Android Appium 原理的学习,Android 4.4 系统之后,Appium 支持使用 ChromeDriver 进行对 Hybrid 页面的自动化测试。那么 iOS 上是怎么做的呢?
iOS 上早期苹果官方就一直提供 iOS webkit debug proxy(这是苹果官方自己开发的私有的通信协议),Appium 集成了该框架,通过它传递指令。

1.2 iOS 9.3 系统之后自动化测试

Appium 在 iOS 下工具的变革

  • iOS 9 之前一直以 instruments 下的 UIAutomation为驱动底层技术(弊端由于 instruments 的限制,单台 mac 只能对应单台设备);
  • iOS 9.3 时代推出 XCUITest 工具,用以替代 UIAutomation;
  • iOS 10 时代苹果直接废弃了 UIAutomation、Facebook 推出 WebDriverAgent(实现的 server 能够支持单台 mac 对应多个设备);
  • Appium 在iOS 9.3 后全面采用 WebDriverAgent 的方案。

1.2.1 关于 WebDriverAgent

  • FaceBook 出品;
  • 实现了一个 server,通过 server 可以远程控制 iOS 设备:启动应用、关闭应用、点击、滚动等操作;
  • 通过连接 XCTest.framework 调用苹果的 API 执行动作;
  • 支持多个设备同时进行自动化;
  • Appium、Macaca 已经集成。

但是 WebDriverAgent 仅仅只提供了一个 server(和 inspect 进行元素定位),并没有像 Appium 一样提供 java 或 python 的 Client 端去写脚本,脚本执行的时候发送指令给 server,然后去运行。WebDriverAgent 要求你自己去实现 Client 端,即拿 Java/ Python 的 WebDriver 库进行封装,然后发送指令。 所以 WebDriverAgent 其实就类似于 Appium server,就只是一个 server。

1.2.2 关于 iOS 9.3 之后的 Appium 自动化架构模式

Appium 很粗暴的把整个 WebDriverAgent 直接集成到自己的项目里,然后通信机制就走 WebDriverAgent,Appium 其实就提供了一个 Client 端的作用。
所以 iOS 9.3 系统之后自动化测试核心是 WebDriverAgent,Appium 就提供了一个 Client 端来写脚本和发送指令。

通过前面的学习,我们知道 Appium 自动化架构模式可以用一个抽象的架构表示,就是下面这样的:
Appium iOS 自动化测试总结_第2张图片
iOS 9.3以及之后的 Appium 自动化架构模式如下图所示:
Appium iOS 自动化测试总结_第3张图片
从图中可以看出:

  • Client 端是 Appium 之前本身提供的;

  • Server 端是:WebDriverAgent 和 Instruments;( Appium 直接把 WebDriverAgent 整个集成进来,Instruments 是为了支持 iOS 9.3 之前的系统)

  • 最右边是一个手机

    1. 之前 Server 是和 bootstrap.jar 通信,这里 WebDriverAgent 提供了 WebDriverAgentRunner (类似 bootstrap.jar 的功能),WebDriverAgent与之通信;
    2. WebDriverAgentRunner 是一个应用,Client 和 server 运行了之后,WebDriverAgentRunner 会被装到手机上,这个应用会接收来自 Server 的指令,并连接底层的 XCTest.framwork,并告诉 XCTest.framwork 操作手机进行自动化。

1.2.3 必装的软件

Xcode、command line tool、libimobiledevice、ios-deploy、carthage、WebDriverAgent、Appium。

  1. libimobiledevice / ideviceinstaller 库,相当于 android 的 adb,是 Appium
    底层用到的工具之一,用于获取 iOS 设备信息。

其常用命令如下:

  • 查看当前所连接的设备

    idevice_id -l # 显示当前所连接设备的 udid
    instruments -s devices # 列出所有设备,包括真机、模拟器、mac
    
  • 安装应用

    ideviceinstaller -u [udid] -i [xxx.ipa] # xxx.ipa 为应用在本地的路径
    
  • 卸载应用

    ideviceinstaller -u [udid] -U [bundleId]
    
  • 查看设备已安装的应用

    ideviceinstaller -u [udid] -l # 查看设备安装的第三方应用
    ideviceinstaller -u [udid] -l -o list_user # 同上,查看设备安装的第三方应用
    ideviceinstaller -u [udid] -l -o list_system # 查看设备安装的系统应用
    ideviceinstaller -u [udid] -l -o list_all # 查看设备安装的所有应用
    
  • 获取设备信息

	ideviceinfo -u [udid] # 获取设备信息
	ideviceinfo -u [udid] -k DeviceName # 获取设备名称 同命令 idevicename
	idevicename # 同上
	ideviceinfo -u [udid] -k ProductVersion # 获取设备版本 10.3.3
	ideviceinfo -u [udid] -k ProductType # 获取设备类型 iPhone 8,1
	ideviceinfo -u [udid] -k ProductName # 获取设备系统名称
  • 其他系统文件信息
	ideviceinfo # 获取设备所有信息
	idevicesyslog # 获取设备日志
	idevicecrashreport -e test # 获取设备 crashlog,test 是文件夹需新建
	idevicediagnostics # 管理设备状态 - 重启、关机、睡眠等
  1. ios-deploy 常用命令
	ios-deploy -c # 查看当前链接的设备
	ios-deploy --[xxx.app] # 安装APP
	ios-deploy --id [udid] --uninstall_only --bundle_id [bundleId] # 卸载应用
	ios-deploy --id [udid] --list_bundle_id # 查看所有应用
	ios-deploy --id [udid] --exists --bundle_id # 查看应用是否安装
  1. carthage,项目依赖管理,主要是 WebDriverAgent 使用,WebDriverAgent 是用它做项目依赖的;
公司 iOS 项目也使用 carthage,类似于 java 的 maven;
  1. ios-deploy、ideviceinstaller 类似 android 的 adb;

  2. authroize-ios,iOS 授权工具,主要用于模拟器中一些权限的授权;

npm install -g authroze-ios
sudo authroze-ios

1.2.4 安装 WebDriverAgent

  1. 从 FB 的 GitHub 上下载WebDriverAgent

    GitHub 上下载WebDriverAgent

  2. 初始化项目

    在 WebDriverAgent 目录下执行:./Scripts/bootstrap.sh

  3. 编译 WebDriverAgent

     a. open WebDriverAgent.xcodeproj(会使用默认打开工具Xcode打开项目)。
     b. 修改 WebDriverAgent.lib 以及 WebDriverAgentRunner 这两个 target 下的 General 和 Build Settings列表(前者是在 mac 上运行的,后者是在手机上运行的)。
     c. General 列表需要修改:签名 Signing 和 BundleId: 签名 Signing:可以用个人免费开发者证书,用任意 AppleId 可申请;BundleId:之前 BundleId 是绑定了 FB team 的证书的,不能使用,所以要改一个新的。 Build Settings列表需要修改 BundleId 和 上一步一样。
     d. WebDriverAgentRunner 是在手机上运行的,要想在手机上安装,需要和上一步一样修改 General 和 Build Settings 列表。
     e. 手机上设置 - 通用 - 描述文件 里信任一下该证书。
     f. Xcode - Product - Test,会安装 WebDriverAgentRunner 并启动 WebDriverAgent 这个 server。
    
  4. 替换 Appium 下的 WebDriverAgent:删除原 WebDriverAgent 文件夹,把编译好的 WebDriverAgent 放进去即可

     a . 如果用 npm 安装的目录在:cd /usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/;
     b. 如果用 desktop 安装的目录在:/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/)
    

1.2.5 开始跑脚本 Sample-Code

1.2.5.1 准备 APP

这里我们需要将TestApp重新编译才能使用。

  1. 进入 APP 其 xxx.xcodeproj 对应的目录,open WebDriverAgent.xcodeproj 打开项目;

  2. 修改该项目里 target 的 General 和 Build Settings列表(和上面一样);

  3. 通过 Xcode 编译运行。

     	或者通过 xcodebuild 命令通过命令行编译运行 xcodebuild -project TestApp.xcodeproj -target TestApp -sdk iphoneos10.3 -configuration
     	development
    

1.2.5.2 准备脚本

  • iOS 项目的 Desired_caps

     Desired_caps:{
     ’platformName’:’iOS’,
     ‘platformVersion’:’10.3.3’,
     ‘devideName’:’iPhone 7 Plus’,
     ‘udid’:’’, #如果是真机的话必须提供
     ‘app’:’~/appPath/app.app’, #app路径,如果只填bundleId,那就是通过id启动已有的App
     }
    
  • iOS 的元素定位

     Appium Desktop - Inspect (推荐)
     WebDriverAgent - Inspector
    

这里说说 Appium Desktop - Inspect 是怎么使用的。
-打开并启动 Appium Desktop,点击软件右上角第一个按钮 “ start inspector session”;
-会出现弹窗,弹窗里配置好 Desired_caps。

  • 定位方式推荐:AccessbilityId

其他Desired_caps配置参见官方文档:https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md

注意
webdriver.py 里只延展定义了针对移动端的 API,is_displayed()、.is_enabled()() 等这些 API 可以去看 WebDriver 即 Slenium 2 本身的。

WebDriver 本身的 API 详见

原文链接:https://testerhome.com/topics/10068

1.3 IOS元素定位方法简单介绍

由于使用id、className、AccessibilityId定位方式较为简单,多数情况下,在同一个页面,都不是唯一存在的,不能识别一个元素。而 xpath定位方式在 xcui 底层原生不支持,由 appium 额外支持的,定位速度很慢,而且有时候定位不到元素的情况存在。综上所述,在 iOS 的 UI 自动化中,使用原生支持的iOSNsPredicateString定位方式是最好,支持也是最好的。

1.3.1 定位方式

iOS 版本全支持,底层测试框架无论是XCUITest 或 UIAutomation,可支持元素的单个属性和多个属性定位,推荐使用。一个元素有这些属性:type、value、name、label、enabled、visible,有些元素的属性只有以上的部分属性,如下图所示,可根据这些属性进行元素定位
Appium iOS 自动化测试总结_第4张图片

1.3.2 元素属性的介绍

type:元素类型,与className作用一致,如:XCUIElementTypeStaticText
value: 一般不用
name:元素的文本内容,可用作 AccessibilityId定位方式,如:测试420班级群
label:绝大多数情况下,与 name 作用一致
enabled:元素是否可点击,一般值为true或者false
visible:元素是否可见,一般值为true或者false

1.3.3 元素定位方式

元素的定位方式都是一个属性+运算符+值形式存在

1、比较运算符:>,<,==,>=,<=,!=
可用于数值和字符串的比较,
如:name>100 或name == ‘测试’

2、范围运算符:IN,BETWEEN
可用于数值和字符串的范围核对
如:name BETWEEN {3,10},name IN {‘Alan’,‘May’}

3、字符串相关:CONTAINS、BEGINSWITH、ENDSWITH
包含某个字符串,如:label CONTAINS ‘测试’
以某个字符串开头,如:label BEGINSWITH ‘420’
以某个字符串结束,如:label ENDSWITH ‘班级群’
PS:在三个关键字后加上[c]不区分大小写,可用于字母的校验;[d]不区分发音符号,即没有重音符号($、#、%等);[cd]即不区分大小写,也不区分发音符号,如:name CONTAINS[c] ABcd和name CONTAINS abcd、name CONTAINS ABCD是等同的,注意后面两个没带[c]的不相等

4、通配符:LIKE
通配符也接受[cd],?代表一个字符,*代表多个字符
如:一个元素的label属性为

label LIKE ‘420测试班级群’

label LIKE ‘420测?班级群’

label LIKE ‘420??班级群’

label LIKE ‘42?测试班?群’

label LIKE ‘*试班级群’

label LIKE ‘420测试班*’

label LIKE ‘42*级群’

label LIKE ‘4群’

以上这么多种文本都可以被识别为同一个元素。

5、正则表达式:MATCHES
如:以4开头,以群结束,

label MATCHES ‘^4.+群$’

1.3.4 以一种属性定位元素

可以用元素的属性:type、value、name、label、enabled、visible,进行定位:

type == XCUIElementTypeStaticText,

label CONTAINS ‘测试’

label LIKE ‘*试班级群’

enabled == true

visible == false

1.3.5 以两种或两种以上属性定位元素

就是以上单个属性定位用符号AND连接起来即可。如:

type == XCUIElementTypeStaticText AND labelCONTAINS '测试

type == XCUIElementTypeStaticText AND labelCONTAINS ‘测试’ AND enabled == true

1.3.6 父子关系、兄弟关系定位

#父子关系定位
self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/title_container").childSelector(text("股票"))')

#兄弟关系定位
self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/title_container").fromParent(text("股票"))')

1.3.7 滚动查找

#滚动查找
self.driver.find_element_by_android_uiautomator('new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("查找的元素文本").instance(0));')

1.3.8 使用方法

// 等于

MobileElement photo = driver.findElementByIosNsPredicate("name= ‘head new‘");

// 模糊匹配

MobileElement photo =driver.findElementByIosNsPredicate("name LIKE ‘*new‘");

// 正则表达式匹配

MobileElement photo = driver.findElementByIosNsPredicate("nameMATCHES ‘^$‘");

// 包含

List<IOSElement> items1 = driver.findElementsByIosNsPredicate("nameCONTAINS ‘我的‘");

// 以"我的"开始

List<IOSElement> items2 = driver.findElementsByIosNsPredicate("nameBEGINSWITH ‘我的‘");

// 以"我的"开始并且以"消息"结尾

List<IOSElement> items3 = driver.findElementsByIosNsPredicate("nameBEGINSWITH ‘我的‘ && name ENDSWITH ‘消息‘");

其中属性名参照inspector的属性字段,关键字LIKE,MATCHES,CONTAINS,BEGINSWITH,ENDSWITH必须是大写,匹配的字符需要用单引号

小坑建议:

  1. 选择定位方式的判断:
      如果显示在界面的文本唯一或是第一个出现:使用accessibility
      如果class唯一或是第一个出现:className
      ID或class不方便定位,控件属性有明确的匹配规则:accessibility
      如果有工具可以直接给出准确的xpath:xpath
      实在不行就用坐标吧
  2. 如果控件的属性visible是false的话,请使用控件坐标并获取中心点用tap点击,直接点击控件会失败

二、Appium 搭建 IOS

可以参考:
wangmcn84作者的模拟器
真机自动化环境搭建
真机自动化环境搭建-实际操作
http://10.0.223.58:8100/status
如果是想查看UI的图层,则可访问http://localhost:8100/inspector,方便书写测试用 已废弃

三、定位方法性能对比

查找元素的顺序,从快到慢:

ios_predicate >> accessibility_id >> class_name >>xpath

(论坛比较多的说法是class_name>>accessibility_id,在这里我们姑且认为它们的速度是一样的。)

  1. ios_predicate:OS 的 UI 自动化中,使用原生支持的Predicate定位方式是最好,可支持元素的单个属性和多个属性定位,强烈推荐使用
    driver.find_element_by_ios_predicate(“value == ‘ClearEmail’”)
    driver.find_element_by_ios_predicate(“type == ‘’ AND value == ‘’)
    https://www.jianshu.com/p/a6c2d72fe704
  2. accessibility_id
    替代以前的name定位方式,在 iOS 上,主要使用元素的label或name(两个属性的值都一样)属性进行定位,如该属性为空,也是不能使用该属性。
    driver.find_element_by_accessibility_id(‘ClearEmail’)
  3. class_name
    使用元素的type属性定位,特别注意该属性的唯一性!class_name唯一的情况并不多,一般情况下用不上。
    driver.find_element_by_class_name(‘XCUIElementTypeButton’)
  4. xpath
    由于 iOS 10开始使用的 XCUITest 框架原生不支持,定位速度很慢,所以官方现在不推荐大家使用,也有其他替代的定位方式可使用。
    1)使用绝对路径定位:
    driver.find_element_by_xpath(’/XCUIElementTypeApplication/XCUIElementTypeButton’)
    2)使用相对路径定位
    driver.find_element_by_xpath(’//XCUIElementTypeButton’)
    3)通过元素的索引定位
    driver.find_element_by_xpath(’//XCUIElementTypeButton[index]’)
    4)通过元素的属性定位
    一种属性:
    driver.find_element_by_xpath(”//className[@value=‘ClearEmail’]“)
    两种属性:
    driver.find_element_by_xpath(”//className[@value=‘ClearEmail’][@ visible =true]“)
    部分属性(最强大):driver.find_element_by_xpath(”//className[contains(@value,‘ClearEmail’)]")
    5)iOSNsPredicateString
    仅支持 iOS 10或以上,可支持元素的单个属性和多个属性定位,推荐使用。
    一种属性:MobileBy.iOSNsPredicateString(“type == ‘XCUIElementTypeButton’”)
    两种属性:MobileBy.iOSNsPredicateString(“type == ‘XCUIElementTypeButton’ AND label == ‘更多信息’”)

四、经典问题

  1. appium测试-操作Android非原生View(自定义)控件(如部分日期和地点选择下拉控件),基于JavaCV的图像匹配方法

  2. Appium使用swipe定位滚动列表和滚动屏幕元素

  3. iOS 测试 ios+appium 自动化 click 无效
    问题现象
    app 页面上可以看到元素,并且通过 find_element_by_xpath 方法也可以定位到,但操作 click 后,页面并未如预期进行跳转,点击实际上没有生效

    问题原因
    通过 self.driver.page_source 获取页面 xml,发现元素属性 visible=‘false’,导致 click 不生效

    解决方法
    用 TouchAction 方法,通过坐标进行点击,python 实现如下

    def touch_on_ele(self, ele):
       x_pos = ele.location['x'] + ele.size['width'] / 2
       y_pos = ele.location['y'] + ele.size['height'] / 2
       TouchAction(self.driver).tap(x=x_pos, y=y_pos).perform()
    

    思路:如果控件的属性visible是false的话,请使用控件坐标并获取中心点用tap点击,直接点击控件会失败

    需要引入 TouchAction 库

    from appium.webdriver.common.touch_action import TouchAction
    
  4. 元素错位 卸载腾讯tbs

  5. IOS原生定位不支持纯数字匹配

五、补充

目前,Appium 支持的定位方式,如下所示:

cssSelector             # Selenium 最强大的定位方法,比 xpath 速度快,但比 xpath 难上手
linkText                # 链接元素的全部显示文字
partialLinkText         # 链接元素的部分显示文字
name                    # 元素的 name 属性,目前官方在移动端去掉这个定位方式,使用 AccessibilityId 替代
tagName                 # 元素的标签名
className               # 元素的 class 属性
id                      # 元素的 id 属性
xpath                   # 比 css 定位方式稍弱一些的定位方法,但胜在容易上手,比较好使用,缺点就是速度慢一些。
AccessibilityId         # Appium 中用于替代 name 定位方式
AndroidUIAutomator      # Android 测试,最强大速度最快的定位方式
iOSNsPredicateString    # iOS 谓词的定位方式,仅支持 XCTest 框架,需大于 iOS 9.3或以上
IosUIAutomation         # iOS 谓词的定位方式,仅支持 UIAutomation 框架,需大于 iOS 9.3或以下
iOSClassChain           # 国外大神 Mykola Mokhnach 开发类似 xpath 的定位方式,仅支持  XCTest 框架,,不如 xpath 和 iOSNsPredicateString 好
windowsAutomation       # windows 应用自动化的定位方式

详细可以参考:https://zhuanlan.zhihu.com/p/28625273

你可能感兴趣的:(自动化,ios,自动化,运维)