Appium Appium - iOS 定位方式 iOSNsPredicateString 详解

DC_ing · 发布于 2017年07月19日 · 最后由 DC_ing 回复于 2017年10月16日 · 2412 次阅读
本帖已被设为精华帖!

iOS 定位方式 iOSNsPredicateString 详解

前言

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

定位方式

iOS 版本全支持,底层测试框架无论是 XCUITest 或 UIAutomation,可支持元素的单个属性和多个属性定位,推荐使用。一个元素有这些属性:typevaluenamelabelenabledvisible,有些元素的属性只有以上的部分属性,如下图所示,可根据这些属性进行元素定位。

元素属性的介绍

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

定位方式

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

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

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

  3. 字符串相关:CONTAINSBEGINSWITHENDSWITH
    包含某个字符串,如:label CONTAINS '测试'
    以某个字符串开头,如:label BEGINSWITH '420'
    以某个字符串结束,如:label ENDSWITH '班级群'
    PS:在三个关键字后加上[c]不区分大小写,可用于字母的校验;[d]不区分发音符号,即没有重音符号($、#、%等);[cd]即不区分大小写,也不区分发音符号,如:name CONTAINS[c] ABcdname CONTAINS abcdname 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.+群$'
    

    PS:具体正则表达式语法,请百度一下,你就知道

以一种属性定位元素

可以用元素的属性:typevaluenamelabelenabledvisible,进行定位:

type == XCUIElementTypeStaticText,
label CONTAINS '测试'
label LIKE '*试班级群'
enabled == true
visible == false

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

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

type == XCUIElementTypeStaticText AND label CONTAINS '测试
type == XCUIElementTypeStaticText AND label CONTAINS '测试' AND enabled == true
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 66 条回复
4845 DC_ing Appium-同一个元素不同定位方式的区别 中提及了此贴 07月19日 09:38
4845 DC_ing appium python 脚本 xpath 报错,求指点 中提及了此贴 07月19日 09:39
Fe45d1

写得很详细,好评~ 不过iOS Predicate在iOS10以下也支持哒

NOTE: iOS predicates are usable in iOS 9.3 and below using the -ios uiautomation locator strategy and they are usable in iOS 10 and above using the -ios predicate string locator strategy

921230

特别好,值得参考,不过有个问题还想请教一个问题:sdk '10.1.1' was not in list of simctl sdks
这个问题解决了,反复出现,大家有没有遇到

4845
DC_ing · #5 · 2017年07月20日 作者
Fe45d1JoTsai 回复

我的错,9.3以下版本没用过,不敢确认,现在我去修改下,感谢指正啊😁

4845 DC_ing 关闭了讨论 07月20日 09:44
4845 DC_ing 重新开启了讨论 07月20日 09:44
104 seveniruby 将本帖设为了精华贴 07月20日 21:04
104

小而美的文章

77d9c0

能举个appium里使用python编写的脚本例子吗,谢谢

15271

“xpath定位方式在 xcui 底层原生不支持” 楼主这句话的意思是iOS10以上都不支持xpath定位吗?

4845
DC_ing · #12 · 2017年07月21日 作者
15271iSteven 回复

不是,在 Appium 和 Macaca 上都支持 xpath 定位,但是这不是底层本身支持的,会有缺陷的

4845
DC_ing · #13 · 2017年07月21日 作者
77d9c0913616672 回复

我在用 java,python 不怎么会啊

5210

学习了,最近马上要弄这一块东西,提前了解下😀

77d9c0
4845DC_ing 回复

java也行啊,嘿嘿😀

4457

type == XCUIElementTypeStaticText不一定能定位到你想要的那个text吧?

214

请问楼主,这个 iOSNsPredicateString 工具 需要单独下载吗

4845
DC_ing · #18 · 2017年07月27日 作者
4457testerwp 回复

如果一个页面,只有一个XCUIElementTypeStaticText,就会定位到。如果多个,就会定位在页面第一个XCUIElementTypeStaticText

4845
DC_ing · #19 · 2017年07月27日 作者
214oscar 回复

这是 appium 本身支持的一种定位方式,不需要重新下载,在代码使用就可以

4845
DC_ing · #20 · 2017年07月27日 作者
104seveniruby 回复

谢谢大神,以后会努力发帖😁

214
4845DC_ing 回复

我看你有几个截图 是用啥打开的

4845
DC_ing · #22 · 2017年07月28日 作者
214oscar 回复

Appium Desktop,新的 appium 客户端

5210

这种定位方式其实就是根据元素的属性进行定位,但是页面上很多的元素的属性其实基本上是一样的,对于这种元素有没有好的办法进行定位呢

4457
5210darkmanno6 回复

相同属性的元素可以生成一个List,然后根据index定位

5210
4457testerwp 回复

如果页面元素很多的话,其实也不是很好判断这个List有多大以及这个元素在List中的位置吧,难道要先打印出来list再来定位吗?

4845
DC_ing · #26 · 2017年08月07日 作者
5210darkmanno6 回复

ios 有些元素是获取不了 text 的值,一般都是将相同的元素生成一个 List,或者在编写用例的时候,强制使用其中一个元素

5210
4845DC_ing 回复

好吧,最近才开始搞这个ios自动化,相较android而言,确实繁杂许多啊😂

4845
DC_ing · #28 · 2017年08月09日 作者
5210darkmanno6 回复

对的,比 android 繁琐好多,很多限制,ios 整个生态决定,没有办法啊

8331

你好 可以举一个简单的例子吗 这个是通过findby 什么定位的 我在 findby列表下没有找到你说的这个定位方式 请指教谢谢

69ae3c

@sysayy 楼主的这个方式应该就是appium里面的findbyid/type
ios底层对id name AccessibilityId是相同的处理

5210
4845DC_ing 回复

我现在使用iOSNSPredicateString的时候发现一个诡异的情况,总是会有发生找不到元素的情况,使用隐式等待也没用,只能到页面之后sleep显示等待才能找到,而xpath基本上能找到,你有碰到过吗?

4845
DC_ing · #32 · 2017年08月15日 作者
5210darkmanno6 回复

遇到过,这个的原因估计是查找元素的动作过后,页面才显示元素。xpath 没事,因为 xpath 速度比较慢。所以这种情况下最好封装下元素查找,让元素在某段时间内,不断地循环查找

4845
DC_ing · #33 · 2017年08月15日 作者
8331sysayy 回复

有的,就是FindsByIosNSPredicate

5210
4845DC_ing 回复

现在用的pagefactory初始化页面元素的,不是很好封装😭

4845
DC_ing · #35 · 2017年08月17日 作者
5210darkmanno6 回复

这个没怎么用过

10714

请教个问题,我们在用appium做iOS端的自动化测试,想通过给控件添加accessibilitylabel的方法实现find_element_by_accessibility的方式获取控件,现在遇到的问题是加完上面的属性后,空间的value,name,label属性的值都变成了我们添加的accessibilitylabel,请问原因是什么啊?

1ef498
4845DC_ing 回复

请教一下,我用了type == XCUIElementTypeCell查找;在页面中有很多个XCUIElementTypeCell;照您的逻辑是找到第一个,我想要的也是第一个cell;可是我这边是直接找不到;然后开始重试;想问一下是怎么回事?

4845
DC_ing · #38 · 2017年08月17日 作者
1ef498_Aaron 回复

先仔细看看你的页面第一个 cell 是不是你想要那个?有时候第一个 cell 在列表之外

4845
DC_ing · #39 · 2017年08月17日 作者
10714myzle 回复

value,name,label这三个属性本来就一致的啊

10714
4845DC_ing 回复

额,我可能没描述清楚,我添加了accessibilitylabel后,value,name, label这三个属性都显示成了ID的值,但是控件本身是有文本信息的,文本信息如何获取?

4845
DC_ing · #41 · 2017年08月18日 作者
10714myzle 回复

你是要先获取元素,再获取文本值?

10714
4845DC_ing 回复

是的,先获取元素,再获取文本,文本是根据数据动态加载的

4845
DC_ing · #43 · 2017年08月18日 作者
10714myzle 回复

appium 的 api 应该有一个元素的 getText()方法的。你可以试试

5210

发现个问题,不知道是不是个例,我用iOSNSPredicate定位一个不在当前屏的元素然后进行点击操作,它居然没有抛NosuchElement的异常但也没有点击成功就这么过去了,看日志也没有什么异常抛出。

4845
DC_ing · #45 · 2017年08月23日 作者
5210darkmanno6 回复

inspector 一下当前屏的元素,看看有没有你所点击的那个元素。如果有,iOSNSPredicate定位肯定没问题的。但因为那个元素不在当前屏,所以肯定没办法点击成功,你试试用其他方式定位那个元素,看看是不是也没有报错

Ae221b
5210darkmanno6 回复

element visible = false , 你把location (x,y),打印下,是不是变成(0,0)了

5210
4845DC_ing 回复

发现如果当前页面超过一屏,使用inspector能解析到屏幕以外的元素,而且isvisible以及enable都是true,所以findElement的时候没有跑出nosuchelement的异常,但是不在当前屏幕上所以点击肯定是没效果的。有点误解啊。。

5210
Ae221bwozhiwan1421 回复

我打印了下元素的信息如下,确实坐标(0,0),isDisplayed为false,但是inspector上的isVisible是true

4845
DC_ing · #49 · 2017年08月24日 作者
5210darkmanno6 回复

所以判断元素是否可用,可以用 isdisplayed 这个方法,而不是直接定位

Ae221b
5210darkmanno6 回复

inspector不是很准确的,你可以在定位element的时候,加上visible = true

5210
Ae221bwozhiwan1421 回复

嗯,加了之后就可以了,被inspector误导了,谢谢

Ae221b
5210darkmanno6 回复

客气了

Eccbe4

正好最近在学这个,太及时,先赞再看。谢谢了先。

9545

为什么我的appium没有iOSNsPredicateString 这个定位方式

Ae221b
9545xiaoyuezuibang 回复

java-client 版本低

9545

我导入了一个Java-client5.0的,也还是没有。但是我的4.1.2版本没有删除,一旦删除4.1.2iosdriver就会报错

Ae221b
9545xiaoyuezuibang 回复

说明你还是用的4.1.2

9545
Ae221bwozhiwan1421 回复

好的,谢谢你!

9545

你好,我从Java-client 5.0 的beta1一直试到beta9 然后又用的java-client 5.0.1和5.0.2 也还是没有driver.findElementByIosNsPredicate。。。可以给个你的那个jar包吗?十分感谢

4845
DC_ing · #60 · 2017年09月12日 作者
9545xiaoyuezuibang 回复

你的 driver 一定要是 iosDriver 才能用的,不然不能用

9545
4845DC_ing 回复

是iosDriver,而且我在我的io.appium.java.client 下也找到了findElementByIosNsPredicate。但是就是不能调用

9545
9545xiaoyuezuibang 回复

我用的是eclipse,请问您用的是什么框架

4845
DC_ing · #63 · 2017年09月12日 作者
9545xiaoyuezuibang 回复

我用的是 IDEA,不过这个应该不跟 IDE 有关系才对啊。你这个要好好看下你的代码才行了

4618

大神这怎么安装?怎么驱动的?

4845
DC_ing · #65 · 2017年10月13日 作者
4618owen 回复

不用另外安装啊,这个 Appium 本身就支持的

66楼 已删除
4618

那是怎么打开这个界面的。是appium 点击start session。然后启动完会出现的界面么

4845
DC_ing · #68 · 2017年10月13日 作者
4618owen 回复

对的,但还是要填写参数

4618
4845DC_ing 回复

大神我配置好了参数,start session 后 ,但是inspector 没有截图显示,无法看到对应元素(app已被驱动开):[debug] [iProxy] Error connecting to device![debug] [JSONWP Proxy] Proxying [GET /screenshot] to [GET http://localhost:8100/session/CDBB28E1-F406-4F6C-AD5C-640A477B63A9/screenshot] with no body[error] [MJSONWP] Encountered internal error running command: ProxyRequestError: Could not proxy command to remote server. Original error: Error: socket hang up
at JWProxy.proxy$ (/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-base-driver/lib/jsonwp-proxy/proxy.js:153:13)
at tryCatch (/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/babel-runtime/regenerator/runtime.js:67:40)
at GeneratorFunctionPrototype.invoke as _invoke
at GeneratorFunctionPrototype.prototype.(anonymous function) as throw
at GeneratorFunctionPrototype.invoke (/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/babel-runtime/regenerator/runtime.js:136:37)
[info] [HTTP] <-- GET /wd/hub/session/0168ffd7-d357-4d0d-94e2-a3d16c5be10b/screenshot 500 17254 ms - 250 [info] [XCUITest] xcodebuild exited with code '65' and signal 'null'

4845
DC_ing · #70 · 2017年10月15日 作者
4618owen 回复

你这是环境没配置好吧

4618
4845DC_ing 回复

可以了 我的Appium 版本有问题 我下载了最新的就好了 那大神 你说的是元素定位 那具体的动作呢?比如click(),有没有个参考例子呢?带动作的那种

4845
DC_ing · #72 · 2017年10月16日 作者
4618owen 回复

元素定位和动作没分开的,动作具体要看这个元素是设什么类型,文本框,按钮还是其他

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册