@DC_ing 貝聊 移動(dòng)開(kāi)發(fā)部 測(cè)試菜鳥(niǎo)
前言
相信大家在使用 Appium 時(shí)特愿,都會(huì)遇到過(guò)一個(gè)問(wèn)題鸿脓,怎么更好地在一個(gè)頁(yè)面中對(duì)某一個(gè)元素進(jìn)行更快速的定位方式中燥。本篇文章基于大家剛接觸 Appium弄慰,對(duì)元素定位還是比較模糊。
Appium 定位方式是依賴(lài)于 Selenium 的橙喘。所以 Selenium 的定位方式,Appium 都支持胶逢,還加上Android 和 iOS 原生的定位方式厅瞎。這樣一下來(lái),就有十多種定位方式初坠,挑選哪一種使用和簸,也是有些講究的。
1. Appium 定位方式種類(lèi)
目前碟刺,Appium 支持的定位方式锁保,如下所示:
cssSelector # Selenium 最強(qiáng)大的定位方法,比 xpath 速度快半沽,但比 xpath 難上手
linkText # 鏈接元素的全部顯示文字
partialLinkText # 鏈接元素的部分顯示文字
name # 元素的 name 屬性爽柒,目前官方在移動(dòng)端去掉這個(gè)定位方式,使用 AccessibilityId 替代
tagName # 元素的標(biāo)簽名
className # 元素的 class 屬性
id # 元素的 id 屬性
xpath # 比 css 定位方式稍弱一些的定位方法抄囚,但勝在容易上手霉赡,比較好使用,缺點(diǎn)就是速度慢一些幔托。
AccessibilityId # Appium 中用于替代 name 定位方式
AndroidUIAutomator # Android 測(cè)試穴亏,最強(qiáng)大速度最快的定位方式
iOSNsPredicateString # iOS 謂詞的定位方式蜂挪,僅支持 XCTest 框架,需大于 iOS 9.3或以上
IosUIAutomation # iOS 謂詞的定位方式嗓化,僅支持 UIAutomation 框架棠涮,需大于 iOS 9.3或以下
iOSClassChain # 國(guó)外大神 Mykola Mokhnach 開(kāi)發(fā)類(lèi)似 xpath 的定位方式,僅支持 XCTest 框架刺覆,严肪,不如 xpath 和 iOSNsPredicateString 好
windowsAutomation # windows 應(yīng)用自動(dòng)化的定位方式
上述所示的定位方式中,name
由于官方的原因廢棄掉谦屑,所以不在這里贅述了驳糯。tagName
、linkText
和 partialLinkText
在我的理解中氢橙,一般是在 web 頁(yè)面使用酝枢,移動(dòng)端很少用。
接下來(lái)悍手,說(shuō)一下我認(rèn)為在 App UI自動(dòng)化中常用到定位方式的詳細(xì)用法帘睦。
1.1 className
使用元素的className
屬性定位,支持:Android 和 iOS坦康,推薦使用竣付。
MobileBy.className("XCUIElementTypeButton")
1.2 id
使用元素的resource-id
屬性定位,支持:Android滞欠,僅支持 Android 4.2或以上古胆,推薦使用,一般來(lái)說(shuō)仑撞,使用 id 能準(zhǔn)確定位赤兴,就使用 id 吧,定位信息簡(jiǎn)潔隧哮,不容易錯(cuò)誤桶良。反正我沒(méi)有在 iOS 用過(guò),大家有正確使用過(guò)的例子沮翔,可以分享一下陨帆。
MobileBy.id("package.name:id/android")
1.3 xpath
支持:Android 和 iOS。但由于 iOS 10開(kāi)始使用的 XCUITest 框架原聲不支持采蚀,定位速度很慢疲牵,所以官方現(xiàn)在不推薦大家使用,也有其他替代的定位方式可使用榆鼠。
-
使用絕對(duì)路徑定位纲爸,如截圖所顯示的 xpath 路徑
MobileBy.xpath("className/className/className/className")
-
使用相對(duì)路徑定位
MobileBy.xpath("http://className")
-
通過(guò)元素的索引定位
MobileBy.xpath("http://className[index]")
-
通過(guò)元素的屬性定位
MobileBy.xpath("http://className[@label='更多信息']") # 使用一種屬性定位 MobileBy.xpath("http://className[@label='更多信息'][@isVisible='1']") # 使用兩種屬性定位 MobileBy.xpath("http://className[contains(@label,'更多')]") # 使用部分屬性定位(最強(qiáng)大)
1.4 AccessibilityId
替代以前的name
定位方式,推薦使用妆够。
在 Android 上识啦,主要使用元素的content-desc屬性
负蚊,如該屬性為空,不能使用此定位方式颓哮。
在 iOS 上家妆,主要使用元素的label
或name
(兩個(gè)屬性的值都一樣)屬性進(jìn)行定位,如該屬性為空冕茅,如該屬性為空伤极,也是不能使用該屬性。
MobileBy.AccessibilityId("更多信息")
1.5 AndroidUIAutomator
僅支持 Android 4.2或以上姨伤,可支持元素的單個(gè)屬性和多個(gè)屬性定位哨坪,推薦使用。
支持元素以下屬性定位:
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)
# 其他一些詳細(xì)方法(包括正則表達(dá)式匹配)姜挺,請(qǐng)查看 Android 源碼中齿税,UiSelector 類(lèi)定義的方法
例子:
MobileBy.AndroidUIAutomator("new UiSelector().text(\"發(fā)送\")") # 使用一種屬性定位
MobileBy.AndroidUIAutomator("new UiSelector().text(\"發(fā)送\").clickable(true)") # 使用兩種屬性定位
元素的所有屬性都可用做定位,功能非常強(qiáng)大炊豪,且速度很快。
1.6 iOSNsPredicate
僅支持 iOS 10或以上拧篮,可支持元素的單個(gè)屬性和多個(gè)屬性定位词渤,推薦使用。詳細(xì)請(qǐng)參照
iOSNsPredicate 定位串绩。
MobileBy.iOSNsPredicateString("type == 'XCUIElementTypeButton'") # 使用一種屬性定位
MobileBy.iOSNsPredicateString("type == 'XCUIElementTypeButton' AND label == '更多信息'") # 使用兩種屬性定位
具體 iOSNsPredicate 語(yǔ)法結(jié)構(gòu)可查看官方文檔缺虐,或查看我另外的一個(gè)帖子。
1.7 iOSClassChain
僅支持 iOS 10或以上礁凡,這是 github 的 Mykola Mokhnach 大神開(kāi)發(fā)高氮,僅限在 WebDriverAgent 框架使用,用于替代 xpath 的顷牌,但使用一陣子后剪芍,感覺(jué)靈活性沒(méi)有 xpath 和 iOSNsPredicate 好,應(yīng)該還不完善吧窟蓝。具體使用方法罪裹,請(qǐng)見(jiàn):iOSClassChain。
MobileBy.iOSClassChain('XCUIElementTypeWindow[1]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/XCUIElementTypeNavigationBar[1]/XCUIElementTypeOther[1]/XCUIElementTypeButton[2]')
1.8 IosUIAutomation
僅支持 iOS 9.3或以下运挫,是 iOS 舊框架 UIAutomation 的定位方式状共,這個(gè)定位類(lèi)型同樣可使用 iOS 謂詞進(jìn)行定位,詳細(xì)可參考:iOSNsPredicate
MobileBy.IosUIAutomation("type == 'UIAButton'") # 使用一種屬性定位
MobileBy.IosUIAutomation("type == 'UIAButton' AND label == '更多信息'") # 使用兩種屬性定位
2. 元素復(fù)雜定位
在貝聊家長(zhǎng)版 Android 的登錄頁(yè)面中谁帕,手機(jī)號(hào)碼輸入框和密碼輸入框兩個(gè)元素信息如下圖所示峡继。
手機(jī)號(hào)碼輸入框和密碼輸入框大部分屬性都一致,單獨(dú)使用 className 和 id 已經(jīng)不可行了匈挖∧肱疲可能有同學(xué)問(wèn)康愤,輸入框不是有默認(rèn)文案(text 屬性)嗎?使用text 屬性定位就可以啦小染。
在初始登錄時(shí)翘瓮,使用這個(gè)text 屬性定位的確可以,但如果不是初始登錄裤翩,手機(jī)號(hào)碼輸入框殘留上次登錄的手機(jī)號(hào)碼资盅,text 屬性就變成上次登錄的手機(jī)號(hào),如 圖3 所示踊赠。
在類(lèi)似這樣的輸入框中呵扛,元素的 text 屬性會(huì)不斷變化。在進(jìn)行元素定位時(shí)筐带,我們會(huì)盡可能避免使用可變化值的屬性進(jìn)行定位今穿。
由此可見(jiàn),手機(jī)號(hào)碼伦籍、密碼兩個(gè)輸入框基本上不能使用單一屬性進(jìn)行定位蓝晒,如果這樣的話,我們可以使用元素多屬性進(jìn)行定位帖鸦。觀察圖1和圖2芝薇,兩個(gè)元素的屬性大部分一致,但還是有3個(gè)屬性是不同的:focused作儿、password洛二、instance。再結(jié)合只有兩個(gè)輸入框相同的屬性值攻锰,這樣一定位晾嘶,即可找到該元素了。
使用 AndroidUIAutomator 定位娶吞。UiSelector 不支持 password 屬性定位垒迂。
# 手機(jī)號(hào)碼輸入框
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 屬性定位
# 手機(jī)號(hào)碼輸入框
MobileBy.xpath("http://android.widget.EditText[@focused='true']")
MobileBy.xpath("http://android.widget.EditText[@password='false']")
# 密碼輸入框
MobileBy.xpath("http://android.widget.EditText[@focused='false']")
MobileBy.xpath("http://android.widget.EditText[@password='true']")
3. 總結(jié)
Appium 元素的一些定位方式寝志,大體上就上面跟大家所說(shuō)的那樣娇斑。只要能將你想要的元素定位到,具體使用哪個(gè)材部,就得看個(gè)人習(xí)慣了毫缆。但如果想要定位的元素,其屬性與其他元素相似較多的話乐导,就需要使用兩種甚至三種屬性進(jìn)行定位了苦丁,具體使用哪些屬性,就得跟其他屬性一一對(duì)比物臂,找出不相同的屬性旺拉,根據(jù)屬性來(lái)使用定位類(lèi)型产上,這樣比較靠譜一些。
本篇文章是本人在學(xué)習(xí) Appium 中所得到的感悟蛾狗,如果大家有更好的方法晋涣,也可以說(shuō)出來(lái),大家一起討論沉桌,一起進(jìn)步谢鹊!