? 通過(guò) uiautomatorviewer.bat工具可以查看控件的屬性璧榄,該工具位于\android-sdk\tools目錄下。需要注意的是笆包,你的手機(jī)設(shè)備或模擬器的API要在16以上目派,也就是Android版本得是4.2以上,因?yàn)檫@個(gè)工具是Google在4.2以后推出來(lái)的喜每,只適用于4.2以后的版本。
*執(zhí)行原理: uiautomatorviewer是發(fā)送dump命令雳攘,讓存放在手機(jī)設(shè)備中/system/bin/uiautomator下的腳本執(zhí)行带兜,獲得一個(gè)uidump.xml的文件,然后將這個(gè)xml文件抓到本地吨灭,本地讀取xml文件就可以了刚照。文件可以看到node節(jié)點(diǎn)的信息:包括package和resource_id等等。
PS:Appium桌面版本也提供定位工具——inspector[放大鏡的圖標(biāo)]喧兄。
? 首先啟動(dòng)模擬器(adb devices查看設(shè)備是否連接)无畔,打開(kāi)uiautomatorviewer.bat工具(功能有:打開(kāi)已保存的截圖;連接設(shè)備桌面吠冤;保存當(dāng)前屏幕截圖):
PS:保存截圖后有兩個(gè)文件浑彰,一個(gè)是屏幕截圖一個(gè)是xml格式的屏幕層級(jí)關(guān)系(uix文件),直接打開(kāi)已保存的截圖咨演,就不用每次都連接設(shè)備打開(kāi)應(yīng)用了闸昨。
#id定位:通過(guò)uiautomatorviewer.bat工具可以查看對(duì)象的id屬性——resource-id。
用法:driver.find_element_by_id("com.android.calculator2:id/digit_1")
注意薄风,如果driver.find_element_by_id("com.android.calculator2:id/digit_1")找不到元素時(shí)饵较,方法會(huì)拋出異常,而driver.find_elements_by_id("com.android.calculator2:id/digit_1")則不會(huì)報(bào)錯(cuò)遭赂,其他driver.find_elements_by_XX方法也是這樣循诉。
#name定位:通過(guò)uiautomatorviewer.bat工具可以查看對(duì)象的name屬性——text(Appium1.5以前的,1.8以后取消了)撇他。
用法:driver.find_element_by_name("1")
#appium_desktop不支持driver.find_element_by_name
#class name定位:通過(guò)uiautomatorviewer.bat工具可以查看對(duì)象的class name屬性——class茄猫。
用法:driver.find_element_by_class_name("android.widget.Button")
使用 class name定位一般獲得的view都不止一個(gè),所以需要遍歷一遍得到的 views困肩,然后縮小搜索條件來(lái)獲得目標(biāo)控件划纽。
比如,先定位一組控件?
list = driver.find_elements_by_class_name("android.widget.Button")
# 循環(huán)遍歷所有控件
for i in list:
print(i)
# 操作某一個(gè)控件
list[0].click()
# 點(diǎn)擊第一個(gè)控件
list[-1].click() # 點(diǎn)擊最后一個(gè)控件
#accessibility id定位:通過(guò)uiautomatorviewer.bat工具可以查看對(duì)象的accessibility id屬性——content-desc锌畸。如果這個(gè)屬性不為空則推薦使用勇劣。[iOS中指的是name屬性]
#xpath定位,xpath是xml path的簡(jiǎn)稱(chēng),是功能強(qiáng)大的一種定位方式:通常使用xpath相對(duì)路徑和屬性定位比默。
說(shuō)明:絕對(duì)路徑以"/"號(hào)表示幻捏,相對(duì)路徑則以"http://"表示。當(dāng)xpath的路徑以"/"開(kāi)頭時(shí)命咐,表示讓xpath解析引擎從文檔的根節(jié)點(diǎn)開(kāi)始解析篡九;當(dāng)xpath路徑以"http://"開(kāi)頭時(shí),則表示讓xpath引擎從文檔的任意符合的元素節(jié)點(diǎn)開(kāi)始進(jìn)行解析醋奠。而當(dāng)"/"出現(xiàn)在xpath路徑中時(shí)榛臼,則表示尋找父節(jié)點(diǎn)的直接子節(jié)點(diǎn);當(dāng)"http://"出現(xiàn)在xpath路徑中時(shí)钝域,則表示尋找父節(jié)點(diǎn)下任意符合條件的子節(jié)點(diǎn)讽坏,不管嵌套了多少層級(jí),所以其實(shí)xpath的路徑可以絕對(duì)路徑和相對(duì)路徑混合在一起來(lái)進(jìn)行表示例证,強(qiáng)大吧B肺亍!织咧!
常用用法:
driver.find_element_by_xpath("http://android.view.ViewGroup/android.widget.Button[7]")
#查找頁(yè)面上第一個(gè)android.view.ViewGroup元素內(nèi)的第7個(gè)android.widget.Button子元素胀葱,即1
driver.find_element_by_xpath("http://android.view.ViewGroup/android.widget.Button[@text='1']")
#查找頁(yè)面上第一個(gè)android.view.ViewGroup元素內(nèi)的text屬性為1的android.widget.Button子元素,即1
driver.find_element_by_xpath("http://android.view.ViewGroup/android.widget.Button[@class='android.widget.Button'][@index='6']")
#查找頁(yè)面上第一個(gè)android.view.ViewGroup元素內(nèi)的class屬性為android.widget.Button并且index屬性為6的android.widget.Button子元素笙蒙,即1
以上用法是xpath中基于準(zhǔn)確元素屬性的定位抵屿,其實(shí)xpath作為定位神器也可以用于模糊匹配:
*contains定位:
driver.find_element_by_xpath("http://android.widget.Button[contains(@resource-id,'1')]")
#查找頁(yè)面上resource-id屬性包含1的android.widget.Button元素
備注:關(guān)于xpath這種定位方式,webdriver會(huì)將整個(gè)頁(yè)面的所有元素進(jìn)行掃描以定位我們所需要的元素捅位,所以這是一個(gè)非常費(fèi)時(shí)的操作轧葛,如果你的腳本中大量使用xpath做元素定位的話,會(huì)導(dǎo)致你的腳本執(zhí)行速度降低艇搀,所以我們還是慎用的尿扯!
#Android uiautomator 定位:通過(guò)android 自帶的android uiautomator的類(lèi)庫(kù)去查找元素。 Appium元素定位方法其實(shí)也是基于Uiautomator來(lái)進(jìn)行封裝的焰雕。
# id 定位driver.find_element_by_android_uiautomator('newUiSelector().resourceId("com.tal.kaoyan:id/login_email_edittext")')
# text定位
driver.find_element_by_android_uiautomator('newUiSelector().text("請(qǐng)輸入用戶名")')
# class name定位driver.find_element_by_android_uiautomator('newUiSelector().className("android.widget.EditText")')
#組合定位
id+textid_text='newUiSelector().resourceId("com.baidu.yuedu:id/webbooktitle").text("小說(shuō)")'driver.find_element_by_android_uiautomator(id_text).click()
# 滾動(dòng)到指定位置self.driver.find_element_by_android_uiautomator('newUiScrollable(''newUiSelector().scrollable(true).instance(0))''.scrollIntoView(''newUiSelector().text("Views").instance(0));').click()