APP自动化基础之元素定位
mobileby
在開始講元素定位的方式時,我們先來看下appium中元素定位的相關模塊:mobileby.py:
在這里可以看到,MobileBy這個類繼承了selenium中的元素定位的類:By,然后根據手機特性又另外自己寫了一堆元素定位的方式。所以理論上,對于android app的元素定位來說,既能使用selenium中的八大元素定位方式,也能使用android所特有的4個定位方式。
從appium inspector看元素定位方式
雖然理論上來說,app的定位方式看起來可選擇的更多了,但由于app的特性,web的很多定位方式在app中就不適用了。比如:link_text、partial_link_text、name、tagname、classname、css_selector都不再適用,因為這些都只適用于html中,而app是xml進行元素標識的,所以這些就用不了了。
接下來我們看下appium inspector的元素屬性區域所展示的這些屬性哪些可以被用來定位。
- id。id確實可以作為app中的一種定位方式,但并不同于web中當前頁面元素的id是唯一的這個特性,在app中id其實是會變化的,同一個id值可能會找到多個元素。所以到了app這邊,通過id的定位方式就沒那么穩定了;
- xpath。很高興又能看到xpath!但其實在appium中,官方是不建議用xpath進行定位的,它是一種脆弱的定位方式,因為它使用的是絕對路徑:
但如果你寫成相對路徑的話,也是可以用來定位的;
- elementId。或許看到有個id你又會高興了。這總該是唯一的了吧!很遺憾,它也是會變化的,所以也不適合用來定位:
- index。這是子標簽的索引,用來標識子標簽是父標簽下的第幾個標簽。這個可以用來輔助定位,比如根據層級關系來找父級或子級:
- text。文本內容,這個也只能用來輔助定位
- class。注意這里的class并不是web中的classname,因為在app中是沒有css的(webapp除外)。這里的class其實相當于web中的tagname,在app中標簽名相同的太多了,所以也不適合用來定位
- package。當前app中所有元素的package都是一樣的
- content-desc。這個屬性比較特別,性必須在輔助瀏覽工具(比如TalkBack)開啟后才能使用,android系統會自動使用人聲朗讀控件上android:contentDescription屬性說指向的內容。這樣用戶就可以知道這個控件是做什么用的。這個屬性主要是讓一些視力有障礙的用戶明白這個控件是干嘛用的。可能你會說,這肯定不會用來做元素定位,一來是它的用途比較特別,而來是很多元素它的content-desc就是空的。但其實content-desc就是app中一種常用的元素定位方式(后面會講到)
- 布爾值屬性。后面有一些只有true或false兩個值的屬性,它們也不太適合用來定位元素,因為很不穩定:
- bounds。元素所在坐標位置。雖然說坐標的值是唯一的,看起來很適合用來作為元素定位方式,但如果你想用這種方式來定位元素的話會相當地麻煩,需要調用TouchAction類下的多個方法。所以這里不推薦用這種方式進行定位
- resource-id。這是android為每個資源單獨分配的id,跟上面id的值是相等的。
app常見定位方式
如何選擇元素定位方式?
app元素定位實戰
id
上面說過,元素定位第一優先選擇的是id,但前提是必須保證id的唯一性。
這里我們定位開始按鈕:
通過search for element查看id的唯一性:
可以看到id是唯一的:
把id方式的元素定位寫進代碼中如下:
xpath
xpath在app中要寫成相對路徑的方式。
這里我們仍然定位的是開始按鈕,找到它的標簽名為:androidx.drawerlayout.widget.DrawerLayout,然后看到它有一個resource-id,我們可以用這個作為輔助的定位方式,即找到一個元素標簽,它具有resource-id的屬性://androidx.drawerlayout.widget.DrawerLayout[@resource-id=“cc.forestapp:id/drawer_layout”]
通過search for element校驗元素表達式的正確性:
可找到一個元素:
寫入代碼中如下:
content-desc
這個元素定位方式真的比較靠運氣,因為很多情況下,元素的這個屬性都是空的,但如果某個元素的這個屬性不是空的,那也是個不錯的定位方式。
這里我們假設開始按鈕的content-desc的值就為開始,那么怎么通過代碼編寫呢?
這里介紹兩種方法:
uiautomator
這是除了id之外最為常用的定位方式了。如果通過id、content-desc都不好定位(如id不唯一或content-desc值為空),那不要用xpath,直接選用uiautomator,因為它的執行速度比xpath快。
直接定位
uiautomator定位方式需要單獨用字符串封裝一段java代碼。在java代碼中,我們先要new一個uiautomator對象,然后通過對象調用方法。
在uiautomator中,每一個屬性在java中都是一個方法,而方法的值就是屬性的值。比如說這里resourceId,在java中就可以這么寫:resourceId(“cc.forestapp:id/button_text”)。所以這里開始按鈕用uiautomator表達式就可以這樣寫:
‘new UiSelector().resourceId(“cc.forestapp:id/button_text”)’
代碼如下:
這里需要注意一點:在java中,字符串必須要用雙引號,不能用單引號。所以python中用字符串封裝java代碼時外面最好用單引號,或者如果非要用雙引號的話,可以在java代碼中字符串部分的雙引號前面加上\進行轉義,表示這就是純粹的單引號,并不代表字符串,就像這樣:
selector = "new UiSelector().resourceId(\"cc.forestapp:id/button_text\")"父級找子級
uiautomator也可以像xpath一樣,根據父級元素找子級元素。
這里依然拿開始按鈕做定位。可以看到開始按鈕元素還有一個父級元素:
我們先定位到父級元素,比如說通過class屬性和enabled屬性進行定位:
className(“android.view.View”).enabled(true)
接著找它下面的子元素,這里我們可以通過resource-id屬性來定位:resourceId(“cc.forestapp:id/button_text”)
合起來就變成這樣:
new UiSelector().className(“android.view.View”).enabled(true).childSelector(new UiSelector().resourceId(“cc.forestapp:id/button_text”))
我們通過search for element來根據uiautomator方式查找元素,是可以找得到的:
寫入代碼中如下:
元素等待
跟web一樣,元素的定位在很多情況下也需要等待。web自動化測試中的三大等待依然使用與app自動化測試,這里不再展開贅述。
常用元素定位輔助工具
除了appium自帶的inspector之外,還有兩款不錯的元素定位的輔助工具:
- android sdk自帶的uiautomator
- 網易出的weditor
好處:1.xpath使用的是相對定位
2.可方便查看package和activity
3.可顯示一個元素的坐標
4.可自動生成python的自動化測試代碼
appium中無法啟動uiautomator2
原因
uiautomator2可能和其他的第三方定位工具(如weditor)同時存在,導致產生兩個adb從而造成沖突
解決方法
- 關閉第三方定位工具,重啟appium server
- 還不行,則刪除真機或模擬器上的appium settings,再次啟動appium server
- 還不行,則重啟模擬器或真機,再次啟動appium server
- 還不行,可停掉uiautomator2的服務
步驟:1.通過以下命令查找uiautomator服務:
adb shell pm list package | grep uiautomator
也可以查看instrumentaion:
adb shell pm list instrumentaion
2.卸載uiautomator2服務
adb uninstall io.appium.uiautomator2.server
adb uninstall io.appium.uiautomator2.server.test
3.重啟appium server
總結
以上是生活随笔為你收集整理的APP自动化基础之元素定位的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 工业网关,工业智能网关
- 下一篇: 第24章 让唯美的雪花飘扬——三维粒子系