[贝聊科技]Appium 元素定位方式大揭秘

@DC_ing 贝聊 移动开发部 测试菜鸟

前言

相信大家在使用 Appium 时,都会遇到过一个问题,怎么更好地在一个页面中对某一个元素进行更快速的定位方式。本篇文章基于大家刚接触 Appium,对元素定位还是比较模糊。

Appium 定位方式是依赖于 Selenium 的。所以 Selenium 的定位方式,Appium 都支持,还加上Android 和 iOS 原生的定位方式。这样一下来,就有十多种定位方式,挑选哪一种使用,也是有些讲究的。

1. Appium 定位方式种类

目前,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 应用自动化的定位方式

上述所示的定位方式中,name由于官方的原因废弃掉,所以不在这里赘述了。tagNamelinkTextpartialLinkText 在我的理解中,一般是在 web 页面使用,移动端很少用。

接下来,说一下我认为在 App UI自动化中常用到定位方式的详细用法。

1.1 className

使用元素的className属性定位,支持:Android 和 iOS,推荐使用。

MobileBy.className("XCUIElementTypeButton")

1.2 id

使用元素的resource-id属性定位,支持:Android,仅支持 Android 4.2或以上,推荐使用,一般来说,使用 id 能准确定位,就使用 id 吧,定位信息简洁,不容易错误。反正我没有在 iOS 用过,大家有正确使用过的例子,可以分享一下。

MobileBy.id("package.name:id/android")

1.3 xpath

支持:Android 和 iOS。但由于 iOS 10开始使用的 XCUITest 框架原声不支持,定位速度很慢,所以官方现在不推荐大家使用,也有其他替代的定位方式可使用。

  1. 使用绝对路径定位,如截图所显示的 xpath 路径

    MobileBy.xpath("className/className/className/className")
    
  2. 使用相对路径定位

    MobileBy.xpath("//className")
    
  3. 通过元素的索引定位

    MobileBy.xpath("//className[index]")
    
  4. 通过元素的属性定位

    MobileBy.xpath("//className[@label='更多信息']")    # 使用一种属性定位
    
    MobileBy.xpath("//className[@label='更多信息'][@isVisible='1']")    # 使用两种属性定位
    MobileBy.xpath("//className[contains(@label,'更多')]")    # 使用部分属性定位(最强大)
    

1.4 AccessibilityId

替代以前的name定位方式,推荐使用。
在 Android 上,主要使用元素的content-desc属性,如该属性为空,不能使用此定位方式。
在 iOS 上,主要使用元素的labelname(两个属性的值都一样)属性进行定位,如该属性为空,如该属性为空,也是不能使用该属性。

MobileBy.AccessibilityId("更多信息")

1.5 AndroidUIAutomator

仅支持 Android 4.2或以上,可支持元素的单个属性和多个属性定位,推荐使用。

支持元素以下属性定位:

index(int index)
text(String text)
resourceId(String id)
className(String className)
packageName(String packageName)
description(String desc)
checked(boolean val)
clickable(boolean val)
enabled(boolean val)
longClickable(boolean val)
password(boolean val)
selected(boolean val)
instance(int val)
# 其他一些详细方法(包括正则表达式匹配),请查看 Android 源码中,UiSelector 类定义的方法

例子:

MobileBy.AndroidUIAutomator("new UiSelector().text(\"发送\")")    # 使用一种属性定位
MobileBy.AndroidUIAutomator("new UiSelector().text(\"发送\").clickable(true)")    # 使用两种属性定位

元素的所有属性都可用做定位,功能非常强大,且速度很快。

1.6 iOSNsPredicate

仅支持 iOS 10或以上,可支持元素的单个属性和多个属性定位,推荐使用。详细请参照
iOSNsPredicate 定位

MobileBy.iOSNsPredicateString("type == 'XCUIElementTypeButton'")    # 使用一种属性定位
MobileBy.iOSNsPredicateString("type == 'XCUIElementTypeButton' AND label == '更多信息'")    # 使用两种属性定位

具体 iOSNsPredicate 语法结构可查看官方文档,或查看我另外的一个帖子。

1.7 iOSClassChain

仅支持 iOS 10或以上,这是 github 的 Mykola Mokhnach 大神开发,仅限在 WebDriverAgent 框架使用,用于替代 xpath 的,但使用一阵子后,感觉灵活性没有 xpath 和 iOSNsPredicate 好,应该还不完善吧。具体使用方法,请见:iOSClassChain

MobileBy.iOSClassChain('XCUIElementTypeWindow[1]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/XCUIElementTypeNavigationBar[1]/XCUIElementTypeOther[1]/XCUIElementTypeButton[2]')

1.8 IosUIAutomation

仅支持 iOS 9.3或以下,是 iOS 旧框架 UIAutomation 的定位方式,这个定位类型同样可使用 iOS 谓词进行定位,详细可参考:iOSNsPredicate

MobileBy.IosUIAutomation("type == 'UIAButton'")     # 使用一种属性定位

MobileBy.IosUIAutomation("type == 'UIAButton' AND label == '更多信息'")    # 使用两种属性定位

2. 元素复杂定位

在贝聊家长版 Android 的登录页面中,手机号码输入框和密码输入框两个元素信息如下图所示。

图1
图2

手机号码输入框和密码输入框大部分属性都一致,单独使用 className 和 id 已经不可行了。可能有同学问,输入框不是有默认文案(text 属性)吗?使用text 属性定位就可以啦。
在初始登录时,使用这个text 属性定位的确可以,但如果不是初始登录,手机号码输入框残留上次登录的手机号码,text 属性就变成上次登录的手机号,如 图3 所示。

图3

在类似这样的输入框中,元素的 text 属性会不断变化。在进行元素定位时,我们会尽可能避免使用可变化值的属性进行定位。

由此可见,手机号码、密码两个输入框基本上不能使用单一属性进行定位,如果这样的话,我们可以使用元素多属性进行定位。观察图1和图2,两个元素的属性大部分一致,但还是有3个属性是不同的:focused、password、instance。再结合只有两个输入框相同的属性值,这样一定位,即可找到该元素了。

使用 AndroidUIAutomator 定位。UiSelector 不支持 password 属性定位。

# 手机号码输入框
MobileBy.AndroidUIAutomator("new UiSelector().resourceId(\"com.babychat:id/edit_content\").focused(true)")
MobileBy.AndroidUIAutomator("new UiSelector().className(\"android.widget.EditText\").instance(0)")

# 密码输入框
MobileBy.AndroidUIAutomator("new UiSelector().resourceId(\"com.babychat:id/edit_content\").focused(false)")
MobileBy.AndroidUIAutomator("new UiSelector().className(\"android.widget.EditText\").instance(1)")

使用 xpath 定位,不支持使用 instance 属性定位

# 手机号码输入框
MobileBy.xpath("//android.widget.EditText[@focused='true']")
MobileBy.xpath("//android.widget.EditText[@password='false']")

# 密码输入框
MobileBy.xpath("//android.widget.EditText[@focused='false']")
MobileBy.xpath("//android.widget.EditText[@password='true']")

3. 总结

Appium 元素的一些定位方式,大体上就上面跟大家所说的那样。只要能将你想要的元素定位到,具体使用哪个,就得看个人习惯了。但如果想要定位的元素,其属性与其他元素相似较多的话,就需要使用两种甚至三种属性进行定位了,具体使用哪些属性,就得跟其他属性一一对比,找出不相同的属性,根据属性来使用定位类型,这样比较靠谱一些。

本篇文章是本人在学习 Appium 中所得到的感悟,如果大家有更好的方法,也可以说出来,大家一起讨论,一起进步!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容