寫完上一篇元素定位的博客,發現實用性基本爲零。這幾天真的煩死我了,一直在找資料,還去看了一遍appium官網文檔。最後結合着selenium的定位方法,測試出幾種可行的元素定位方法。android
什麼是層級定位呢?web
在不少的自動化中若是隻是靠簡單的定位是沒有辦法完成自動化的。有的元素的id、name、className都是同樣的,xpath定位效率低下,而且在appium中,可使用的屬性很是少,這個時候咱們就須要使用層級定位了。數組
咱們能夠看到,QQ天氣和微視的class都是相同的, 接下來咱們用代碼試一試。app
# coding:utf-8 from appium import webdriver from time import sleep # 初始化 desired_caps = {} # 使用哪一種移動平臺 desired_caps['platformName'] = 'Android' # Android版本 desired_caps['platformVersion'] = '5.1.1' #使用adb devices -l 查詢,當有多臺設備時,須要聲明 desired_caps['deviceName'] = '127.0.0.1:62001' #包名 desired_caps['appPackage'] = 'com.tencent.mobileqq' #界面名 desired_caps['appActivity'] = '.activity.SplashActivity' #不清除數據 desired_caps['noReset'] = 'True' # 啓動服務 driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) driver.find_element_by_id('com.tencent.mobileqq:id/recent_chat_list') driver.find_element_by_class_name('android.widget.LinearLayout').click() #退出driver driver.quit()
運行後,咱們會發現代碼執行了,也沒有報錯,可是也不會點擊,這是爲何呢。這就牽扯到另一個定位問題,就是下面要說的List定位。測試
list顧名思義就是一個列表。當咱們想要獲取一個元素,可是卻發現符合條件的元素有不少個的時候,咱們就能夠選擇List定位了。由於元素的個數的不肯定性,因此咱們的方法也須要變成複數,因此這裏須要用複數,因此在咱們定位時咱們不可以接着用find_element_by_class_name等等定位方式了,咱們須要用他的複數形式find_elements_by_class_name,全部的定位方式都同樣須要採用複數加s。ui
driver.find_element_by_id('com.tencent.mobileqq:id/recent_chat_list') driver.find_elements_by_class_name('android.widget.LinearLayout')
上面的代碼最後選擇的是com.tencent.mobileqq:id/recent_chat_list父節點下全部android.widget.LinearLayout子節點,如今咱們如何去操做這些子節點呢,有兩種方法:spa
一、List是一個集合,這裏定位的全部子節點最後就成了個list,若是咱們要訪問這個list裏面的某一個元素咱們能夠像訪問數組中的數據同樣經過下標訪問。最後的代碼就是下面這個樣子:.net
driver.find_element_by_id('com.tencent.mobileqq:id/recent_chat_list') elements = driver.find_elements_by_class_name('android.widget.LinearLayout') elements[0].click() #讓咱們更好的觀看效果 sleep(5)
二、若是你要訪問List裏面的元素,那麼咱們是否能夠經過for循環語句來依次訪問呢?這個在自動化中會常常用到。下面你能夠經過這個思路本身去實戰一下,看可否達到預期效果。下面看個人代碼:code
for element in elements: sleep(2) element.click()
看上面的代碼,咱們經過循環去訪問這個list裏面的每個元素,由於每次循環獲得的都是其中一個元素,那麼咱們只須要在這個元素上加上你想要的操做便可,因此咱們這裏能夠直接點擊進去。orm
可是咱們會發現,在進入到第一個標籤後,系統就會報錯,爲何呢?由於界面跳轉到微視裏面了,而裏面沒有android.widget.LinearLayout元素,因此就會由於找不到元素而報錯。
因此這種方法的使用有限制,只能在那種不須要界面跳轉的狀況下使用。
xpath定位能夠分爲兩種,絕對定位和相對定位。
可是咱們會發現,絕對定位的路徑很是的長,後期代碼也比較麻煩,開發中幾乎不可能使用。(老大看到了就叼你)
相對路徑就是很是好用的一種了,不斷簡短,後期維護代碼也方便。
如下就是相對路徑的使用了:
我使用的是taptap軟件來進行測試,你們能夠換成其餘軟件。
(1) 若是當前class內存在惟一text能夠定位元素,直接用當前class+text,例如:
# coding:utf-8 from appium import webdriver from time import sleep from appium.webdriver.common.touch_action import TouchAction # 初始化 desired_caps = {} # 使用哪一種移動平臺 desired_caps['platformName'] = 'Android' # Android版本 desired_caps['platformVersion'] = '5.1.1' #使用adb devices -l 查詢,當有多臺設備時,須要聲明 desired_caps['deviceName'] = '127.0.0.1:62001' #包名 desired_caps['appPackage'] = 'com.taptap' #界面名 desired_caps['appActivity'] = 'com.play.taptap.ui.MainAct' #不清除數據 desired_caps['noReset'] = 'True' #啓動服務 driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) element = driver.find_element_by_xpath('//android.widget.TextView[@text="排行"]') TouchAction(driver).tap(element).perform() sleep(5) #退出driver driver.quit()
(2) 若是當前class內,resource-id、text二者能惟必定位元素,直接用當前class+二者並列,例如:
element1 = driver.find_element_by_xpath('//android.widget.TextView[@text="個人遊戲"]') TouchAction(driver).tap(element1).perform() sleep(2) element2 = driver.find_element_by_xpath('//android.widget.TextView[@resource-id="com.taptap:id/app_title" and @text="第五人格T"]') TouchAction(driver).tap(element2).perform() sleep(5)
(3) 若是當前class內,text中的文本內容不是徹底符合,但能匹配部份內容,可用當前class+模糊定位contains,例如:
element = driver.find_element_by_xpath('//android.widget.TextView[contains(@text,"個人")]') TouchAction(driver).tap(element).perform() sleep(2)
還有不少相似的定位方法,能夠查看我找到的一個大佬寫的博客:https://blog.csdn.net/Dome_/article/details/80638245
整體上就這樣了,之後若是找到更好的方法,就再更新一章。