元素获取的方法
自动化测试过程中,如何定位页面元素是很多人都会纠结的问题,只要找到相应的元素,其他的事情相对来说就简单很多了。本文主要介绍iOS平台下获取页面元素的常用方法,我按照推荐使用顺序列举如下:
- findElement(s)ByAccessibilityId
这是我最推荐的方法,原因是简单粗暴上手快!但是这个方法不是任何地方都能用,只有元素设置了AccessibilityId
属性才能够使用。但是绝大部分程序员都懒的主动设置这个属性,所以使用这种方法获取元素只能解决很小一部分问题。
可以通过给
NSObject
的accessibilityLabel
赋值来设置AccessibilityId
;另外Storyboard和Interface Builder中可以设置AccessibilityId
;还有一些控件(如UILabel
和UIButton
)会使用它们上面的字符串作为AccessibilityId
的值;图片会使用它们在assets中的名字作为AccessibilityId
的值
- findElement(s)ByIosNsPredicate
使用NSPredicate
来查找元素是XCUITest
支持的一种方式,所以这个方法是比较通用的方法。它的查找效率比较快,但是需要记住NSPredicate
的一些简单语法才能使用(语法规则见下一节),上手比较慢。 - findElement(s)ByClassName
这个方法也是比较推荐的,可以根据元素的类型获取到一个或者多个相关元素,上手比较快,但是难点在于怎么从一组相关元素中找到我们需要的那个元素。 - findElement(s)ByXPath
初学者一般都习惯于用这个方法,因为使用Inspector查看页面元素的时候,在无法使用AccessibilityId
的时候,会给出XPath,很多初学者就直接使用了这个XPath。遗憾的是,在XCUITest
框架并不支持XPath,之所以能在Appium使用XPath,是因为Appium的扩展。因为不是原生支持的,所以使用起来效率会比较慢,还存在查找不到的风险。这个方法也是我极力不推荐的。
多个元素的选择
当使用上面的方法获取到多个元素到时候,该怎么正确选择需要的元素呢?
当在Inspector中查看页面元素时可以发现整个页面是以XML文档的形式描述的,文档的每一个节点都对应一个元素。XML文档可以使用一棵树来表示,对于树的遍历常用的算法有深度优先搜索和宽度优先搜索两种,根据我的观察(因为无法找到selenium的源代码,无法从源代码分析),appium应该是是用宽度优先搜索算法,所以可以根据宽度优先搜索的顺序来确定获取到的元素列表中哪个元素是需要的。
获取子元素
有时候需要在某个父元素下面查找某个子元素,这时候可以这样做:
假设父元素是a,使用a.findElementByXXX
来获取某个子元素,使用a.findElementsByXXX
来获取某类子元素,但是这种使用方式不能用于IosNsPredicate
。
要想正常使用IosNsPredicate,只能使用级联调用:
driver.findElementByXXX.findElementsByXXX.get(y).findElementByXXX
为什么
IosNsPredicate
不能直接使用父元素调用,现在还不知道,后续会抽空研究。
NSPredicate在元素获取中的用法
NSPredicate
是iOS开发中模式匹配的最主要的一个类,有时候使用它可以有效的找到需要的元素,本节将介绍它在元素查找时的主要语法。
语法模式
NSPredicate
的语法模式是:属性+操作符+值
,例如
type == 'XCUIElementTypeTextField'
label LIKE 'ABC*'
name MATCHES '^abc.+'
上文中,type、label和name是属性,==、LIKE和MATCHES是操作符,'XCUIElementTypeTextField'、'ABC*'和'^abc.+'是值。
属性
Appium支持的元素属性如下:
- type:元素的类型
- name:元素的文本内容,大部分情况下与label作用相同
- value:元素的值,一般不怎么用
- label:大部分情况下与name作用相同
- enable:元素是否可点击,一般值是true或者false
- visible:元素是否可见,一般值是true或者false
这些值都可以在Inspector中查阅到。
操作符
Appium支持的属性操作符如下:
- 比较运算符:用于数字和字符串的比较,包含>, <, ==, >=, <=, !=
- 范围运算符:BETWEEN, IN
label BETWEEN {3, 9}
name IN {'科目一', '科目二'}
- 字符串操作:CONTAINS, BEGINSWITH, ENDSWITH
在它们后面加上[c]表示不区分大小写,加上[d]表示不区分发音符号
name CONTAINS[c] 'abc'
value BEGINSWITH[cd] 'abc'
- 正则表达式:MATCHES
name MATCHES '^ABC.+'
iOS正则表达式的规则请自行查阅相关文档
- LIKE
LIKE的值中,?表示一个字符,*表示多个字符
name LIKE 'abc?' #匹配abcd,不匹配abcde
name LIKE 'abc*' #匹配abcd和abcde
逻辑操作
可以使用逻辑操作将多个NSPredicate
连接在一起,支持的逻辑操作如下:
- AND
- OR
- NOT
注意事项和小技巧
下面是我总结的一些注意事项和小技巧
- Appium无法直接获取toast
- 如果获取的某个元素不响应请求,可以考虑获取它的父节点看看能否响应
- 收起键盘:driver.hideKeyboard()
- 调用键盘的功能性按钮,如“搜索”、“完成”、“下一项”:element.sendKeys("\n")
本文如有错误,欢迎交流指正!