[貝聊科技]Appium 元素定位方式大揭秘
前言
相信大家在使用 Appium 時,都會遇到過一個問題,怎麼更好地在一個頁面中對某一個元素進行更快速的定位方式。本篇文章基於大家剛接觸 Appium,對元素定位還是比較模糊。
Appium 定位方式是依賴於 Selenium 的。所以 Selenium 的定位方式,Appium 都支持,還加上Android 和 iOS 原生的定位方式。這樣一下來,就有十多種定位方式,挑選哪一種使用,也是有些講究的。
1. Appium 定位方式種類
目前,Appium 支持的定位方式,如下所示:
cssSelector # Selenium 最強大的定位方法,比 xpath 速度快,但比 xpath 難上手nlinkText # 鏈接元素的全部顯示文字npartialLinkText # 鏈接元素的部分顯示文字nname # 元素的 name 屬性,目前官方在移動端去掉這個定位方式,使用 AccessibilityId 替代ntagName # 元素的標籤名nclassName # 元素的 class 屬性nid # 元素的 id 屬性nxpath # 比 css 定位方式稍弱一些的定位方法,但勝在容易上手,比較好使用,缺點就是速度慢一些。nAccessibilityId # Appium 中用於替代 name 定位方式nAndroidUIAutomator # Android 測試,最強大速度最快的定位方式niOSNsPredicateString # iOS 謂詞的定位方式,僅支持 XCTest 框架,需大於 iOS 9.3或以上nIosUIAutomation # iOS 謂詞的定位方式,僅支持 UIAutomation 框架,需大於 iOS 9.3或以下niOSClassChain # 國外大神 Mykola Mokhnach 開發類似 xpath 的定位方式,僅支持 XCTest 框架,,不如 xpath 和 iOSNsPredicateString 好nwindowsAutomation # windows 應用自動化的定位方式n
上述所示的定位方式中,name由於官方的原因廢棄掉,所以不在這裡贅述了。tagName、linkText 和 partialLinkText 在我的理解中,一般是在 web 頁面使用,移動端很少用。
接下來,說一下我認為在 App UI自動化中常用到定位方式的詳細用法。
1.1 className
使用元素的className屬性定位,支持:Android 和 iOS,推薦使用。
MobileBy.className("XCUIElementTypeButton")n
1.2 id
使用元素的resource-id屬性定位,支持:Android,僅支持 Android 4.2或以上,推薦使用,一般來說,使用 id 能準確定位,就使用 id 吧,定位信息簡潔,不容易錯誤。反正我沒有在 iOS 用過,大家有正確使用過的例子,可以分享一下。
MobileBy.id("package.name:id/android")n
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 上,主要使用元素的label或name(兩個屬性的值都一樣)屬性進行定位,如該屬性為空,如該屬性為空,也是不能使用該屬性。MobileBy.AccessibilityId("更多信息")n
1.5 AndroidUIAutomator
僅支持 Android 4.2或以上,可支持元素的單個屬性和多個屬性定位,推薦使用。
支持元素以下屬性定位:
index(int index)ntext(String text)nresourceId(String id)nclassName(String className)npackageName(String packageName)ndescription(String desc)nchecked(boolean val)nclickable(boolean val)nenabled(boolean val)nlongClickable(boolean val)npassword(boolean val)nselected(boolean val)ninstance(int val)n# 其他一些詳細方法(包括正則表達式匹配),請查看 Android 源碼中,UiSelector 類定義的方法n
例子:
MobileBy.AndroidUIAutomator("new UiSelector().text("發送")") # 使用一種屬性定位nMobileBy.AndroidUIAutomator("new UiSelector().text("發送").clickable(true)") # 使用兩種屬性定位n
元素的所有屬性都可用做定位,功能非常強大,且速度很快。
1.6 iOSNsPredicate
僅支持 iOS 10或以上,可支持元素的單個屬性和多個屬性定位,推薦使用。詳細請參照
iOSNsPredicate 定位。MobileBy.iOSNsPredicateString("type == XCUIElementTypeButton") # 使用一種屬性定位nMobileBy.iOSNsPredicateString("type == XCUIElementTypeButton AND label == 更多信息") # 使用兩種屬性定位n
具體 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])n
1.8 IosUIAutomation
僅支持 iOS 9.3或以下,是 iOS 舊框架 UIAutomation 的定位方式,這個定位類型同樣可使用 iOS 謂詞進行定位,詳細可參考:iOSNsPredicate
MobileBy.IosUIAutomation("type == UIAButton") # 使用一種屬性定位nnMobileBy.IosUIAutomation("type == UIAButton AND label == 更多信息") # 使用兩種屬性定位n
2. 元素複雜定位
在貝聊家長版 Android 的登錄頁面中,手機號碼輸入框和密碼輸入框兩個元素信息如下圖所示。
圖1
圖2
手機號碼輸入框和密碼輸入框大部分屬性都一致,單獨使用 className 和 id 已經不可行了。可能有同學問,輸入框不是有默認文案(text 屬性)嗎?使用text 屬性定位就可以啦。
在初始登錄時,使用這個text 屬性定位的確可以,但如果不是初始登錄,手機號碼輸入框殘留上次登錄的手機號碼,text 屬性就變成上次登錄的手機號,如 圖3 所示。圖3
在類似這樣的輸入框中,元素的 text 屬性會不斷變化。在進行元素定位時,我們會儘可能避免使用可變化值的屬性進行定位。
由此可見,手機號碼、密碼兩個輸入框基本上不能使用單一屬性進行定位,如果這樣的話,我們可以使用元素多屬性進行定位。觀察圖1和圖2,兩個元素的屬性大部分一致,但還是有3個屬性是不同的:focused、password、instance。再結合只有兩個輸入框相同的屬性值,這樣一定位,即可找到該元素了。
使用 AndroidUIAutomator 定位。UiSelector 不支持 password 屬性定位。
# 手機號碼輸入框nMobileBy.AndroidUIAutomator("new UiSelector().resourceId("com.babychat:id/edit_content").focused(true)")nMobileBy.AndroidUIAutomator("new UiSelector().className("android.widget.EditText").instance(0)")nn# 密碼輸入框nMobileBy.AndroidUIAutomator("new UiSelector().resourceId("com.babychat:id/edit_content").focused(false)")nMobileBy.AndroidUIAutomator("new UiSelector().className("android.widget.EditText").instance(1)")n
使用 xpath 定位,不支持使用 instance 屬性定位
# 手機號碼輸入框nMobileBy.xpath("//android.widget.EditText[@focused=true]")nMobileBy.xpath("//android.widget.EditText[@password=false]")nn# 密碼輸入框nMobileBy.xpath("//android.widget.EditText[@focused=false]")nMobileBy.xpath("//android.widget.EditText[@password=true]")n
3. 總結
Appium 元素的一些定位方式,大體上就上面跟大家所說的那樣。只要能將你想要的元素定位到,具體使用哪個,就得看個人習慣了。但如果想要定位的元素,其屬性與其他元素相似較多的話,就需要使用兩種甚至三種屬性進行定位了,具體使用哪些屬性,就得跟其他屬性一一對比,找出不相同的屬性,根據屬性來使用定位類型,這樣比較靠譜一些。
本篇文章是本人在學習 Appium 中所得到的感悟,如果大家有更好的方法,也可以說出來,大家一起討論,一起進步!
推薦閱讀:
※[從入門到不放棄]多瀏覽器的自動化測試(2)-雲服務測試
※Kotlin 來了,對APP測試意味著什麼
※性能測試基礎
※我也終於用上Powershell了
※Android獲取應用大小
TAG:自动化测试 |