一、常用元素定位方法
appium從selenium中繼承了所有的元素定位方法, 並且增加了一些自己的元素定位方式,下方截圖分別為selenium和MobileBy包原始碼:
但是從繼承selenium中的定位方法中,一般只會用到id、class_name、xpath這三種方法,總結起來,appium中常用的定位方法一般有以下五種:
- 通過id定位:resource-id
- 通過class_name定位:class
- 通過accessibility_id定位:content-desc
- 通過android_uiautomator定位:SDK自帶的java開發的uiautomator自動化框架
- 通過xpath定位
1.1 使用id定位
通過工具獲取到按鈕的resource-id,注意這裡是使用resource-id,而不是id,
driver.find_element_by_id() 或者 MobileBy.ID
loc = (MobileBy.ID, 'com.wm.dmall:id/tv_positive')
或driver.find_element_by_id('com.wm.dmall:id/tv_positive')
1.2 class_name定位
在上述截圖中雖然含有class,但其實不建議使用class name定位,因為同一頁面含有重複的class,但是可以通過下標指定哪一個class,如下程式碼:
driver.find_elements_by_class_name('android.widget.TextView')[1]
注:下標的方式雖然可以定位出元素,但是也有弊端,前端移動順序後,UI程式碼也要隨之改變。
1.3 通過text定位(已廢棄)
appium1.5及之後的版本廢棄了name屬性(如name=百度一下),需要使用uiautomator的定位方式,使用text的內容,下面會詳解uiautomator。
1.4 accessibility_id定位
在UI Automator Viewer介面上並沒有找到這個欄位,這個對應的欄位是content-desc,
driver.find_element_by_accessibility_id() 或者 MobileBy.ACCESSIBILITY_ID,程式碼如下:
driver.find_element_by_accessibility_id("accessibility_id值") 或loc = (MobileBy.ACCESSIBILITY_ID, 'accessibility_id值')
1.5 android_uiautomator定位
相當於使用 UiAutomator Api 去遞迴地搜尋元素(Android 專屬),可以說android uiautomator是終極定位方式,有的時候一些元素不能夠很好的定位時,那麼就需要採用android uiautomator去定位,他是一種非常強有力的定位方式,原理是通過android 自帶的android uiautomator的類庫去查詢元素。appium對android 的uiautomator進行了封裝,該方法的引數為UiSelector類定位元素的表示式:new UiSelector().屬性('屬性值'),例項化一個UiSelector物件,然後通過例項介面呼叫。
AndroidUIAutomator是一個強有力的元素定位方式,它是通過Android UIAutomator類庫去找元素,可以選擇resourceId、text、className、description作為傳入的字串。
1.5.1 android_uiautomator之text文字定位語法
1.使用text文字定義
loc_text = 'new UiSelector().text("登入/註冊")' driver.find_element_by_android_uiautomator(loc_text).click()
2.uiautomator text模糊定位
文字比較長的時候,可以用textContains模糊匹配,通過text的部分資訊就能夠進行定位,我們直接看程式碼:
loc_text = 'new UiSelector().textContains("登入/註冊")' driver.find_element_by_android_uiautomator(loc_text).click()
在上面的程式碼中我們只是將.text()的方法變成了.textContains(),在方法中傳入模糊的資料就好。看到這裡是否有人思考過一個問題,既然有類似的模糊尋找,那麼有沒有像正規表示式一樣的查詢呢?答案是肯定的,看我們下面的方法。
3.textMatches 正則匹配查詢
textMatches故名思義就是通過正則的來進行查詢定位,也是通過text的屬性來進行正則匹配,我們直接看程式碼:
loc_text = 'new UiSelector().textMatches("^登入/.*")' driver.find_element_by_android_uiautomator(loc_text).click()
4.textStartsWith是以某個文字開頭來匹配
new UiSelector().textStartsWith("以text文字開頭")
loc_text = 'new UiSelector().textStartsWith("登入")' driver.find_element_by_android_uiautomator(loc_text).click()
1.5.2 android_uiautomator之resourceId定位
resourceId定位和appium封裝好的id定位是一樣的,只是這裡將寫法變成了uiautomator的寫法而已。
1.resourceId定位
oc_id = 'new UiSelector().resourceId(" com.wm.dmall:id/net_image_view ")' driver.find_element_by_android_uiautomator(loc_id).click()
通過上面的程式碼和之前的程式碼對比大家可能發現其實他們前面都是一樣的,只是在定位的時候發生了一些變化,text變換成了resourceId即可,也就是頁面物件屬性的資訊進行變更了,其他方法都是一樣。
2. resourceIDMatches 定位
通過id進行正則匹配定位
loc_id = 'new UiSelector().resourceIdMatches(".+net_image_view ")' driver.find_element_by_android_uiautomator(loc_id).click()
1.5.3 android_uiautomator之className定位
頁面上的class屬性一般不唯一,多半用在複數定位時候。比如通過class屬性定位'同意'這個按鈕下標就是1。
1.className定位
# className複數定位 loc_class = 'new UiSelector().className("android.widget.TextView")' driver.find_elements_by_android_uiautomator(loc_class)[1].click()
2.uiautomator classNameMatches定位
通過className正則匹配進行定位:
loc_class = 'new UiSelector().classNameMatches (".*widget.TextView")' driver.find_elements_by_android_uiautomator(loc_class)[1].click()
1.5.4 android_uiautomator之description定位
loc_id = 'new UiSelector(). description("多點")' driver.find_element_by_android_uiautomator(loc_id).click()
1.5.5 android_uiautomator之組合定位
1.id與text屬性組合
id_text = 'resourceId("com.wm.dmall:id/funcTitle").text("待支付")' driver.find_element_by_android_uiautomator(id_text).click()
2.class與text屬性組合
class_text = 'className("android.widget.TextView").text("待支付")' driver.find_element_by_android_uiautomator(class_text).click()
3.父子關係定位
son = 'resourceId("com.wm.dmall:id/container").childSelector(text("我的"))' driver.find_element_by_android_uiautomator(son).click()
4.兄弟定位fromParent
有時候父元素不好定位,但是跟他相鄰的兄弟元素很好定位,這時候就可以通過兄弟元素,找到同一父級元素下的子元素。
brother = 'resourceId("com.wm.dmall:id/nav_item_laber_tv").fromParent(text("我的"))' driver.find_element_by_android_uiautomator(brother).click()