對象定位是自動化測試中很關鍵的一步,也能夠說是最關鍵的一步,畢竟你對象都沒定位那麼你想操做也不行。因此本章節的知識我但願你們多動手去操做,不要僅僅只是書本上的知識,畢竟這個我只可以舉例說明。下面咱們來看咱們經常使用的一些定位方式html
find_element_by_id()
find_element_by_name() #appium較新版本name定位被去掉
find_element_by_class_name()
find_element_by_xpath()
python
項目使用的工具是uiautomatorviewer,在安卓sdk的tools目錄下(C:\Program Files (x86)\Android\androidSDK\tools,查看環境搭建章節)android
不管是在web自動化仍是app自動化中id都是惟一的web
面圖片中左邊部分用紅色圈出來的對象的id咱們在右邊的屬性中能夠看到,他的id我一樣是用紅色圈出,若是咱們須要對「點擊相機,搜你所見」這個輸入框進行輸入信息,咱們只需操做右邊的id就行,下面咱們直接看代碼app
#!/usr/bin/env python # -*- codinfg:utf-8 -*- ''' @author: Jeff LEE @file: 啓動百度.py @time: 2018-07-25 15:24 @desc: ''' import time from appium import webdriver desired_caps={ 'platformName':'Android', 'deviceName':'D3F021C19001219', #手機設備名稱,經過adb devices查看 'platformVersion':'4.4', #android系統的版本號 'unicodeKeyboard':'True', 'resetKeyboard':'True', 'appPackage':'com.baidu.searchbox',#apk包名 'appActivity':'com.baidu.searchbox.SplashActivity', #apk的launcherActivity } driver=webdriver.Remote('http://localhost:4723/wd/hub',desired_caps) time.sleep(5) # 點擊「輸入框」 driver.find_element_by_id("com.baidu.searchbox:id/baidu_searchbox").click() time.sleep(3) # 輸入字段 searchInputBox = driver.find_element_by_id('com.baidu.searchbox:id/SearchTextInput') searchInputBox.send_keys("Appium") time.sleep(3) driver.quit()
經過上面的代碼咱們可以直接在輸入框中輸入Appium,以下圖所示工具
在實際工做中className定位用得相對而言會比較少。當你常常去看class時你會發現不少的className是同樣的,你沒有辦法對其進行惟必定位,下面咱們看下面兩張圖片測試
經過className定位的代碼ui
driver.find_element_by_class_name('android.widget.TextView')
這種方式去定位,你會發現你永遠定位不了‘appium原理’,這是爲何呢?由於在設計的時候若是你查找的元素在頁面有多個,系統會自動給你選擇第一個,因此你永遠操做不了後面的,那如何解決這種問題呢?咱們看後面講解。spa
xpath定位在web自動化中是最多見的,並且也是最有效的,使用xpath定位避免了找不到元素致使報錯的問題,可是在app中使用xpath定位是一件很low的事情。爲何這麼說呢?由於在做者的經歷中只要碰見使用xpath定位元素他的反應就會比較慢,自動化的目的是爲了提升效率,可是使用xpath後會下降效率,因此這裏說很 low。設計
經過xpath定位的代碼
driver.find_element_by_xpath('//android.widget.TextView[@text="appium原理"]').click()
運行結果
在xpath裏面咱們的語法是這樣'//android.widget.TextView[@text="appium原理"]',這個和咱們以前web的xpath同樣,意思是查找全部節點中節點爲android.widget.TextView (這裏使用的是text,也可使用id或class等元素,系統會依次去找)而且他的text屬性值爲appium原理,這樣是否更容易理解呢?下來多練習。這樣的定位方式不推薦,效率很慢。
在前面的章節中咱們已經提到了層級定位,只是不知道具體怎麼操做而已。在不少的自動化中若是隻是靠簡單的定位是沒有辦法完成自動化的,就像剛xpath定位同樣,有的元素的id、className都是同樣的,xpath定位效率低下,這個時候咱們大多數都會採用層級定位。
從上面的圖片咱們能夠看出id爲android.widget.TabWidget的節點下面包含了不少的android.widget.FrameLayout
從這張圖片咱們不難看出,若是咱們要定位這個元素咱們是沒辦法去定位的,這種狀況咱們大多數使用的是層級定位以及xpath,這裏咱們來看如何使用層級定位。
首先咱們能夠看出兩幅圖的結構上的區別,第二幅圖元素他是在第一幅圖裏面的,這裏咱們稱第一幅圖id爲android:id/tabs的節點爲第二幅圖元素的父節點,咱們只須要先經過id定位到父節點,而後再從父節點往下面進行定位第二幅圖就能夠了
elemet =driver.find_element_by_id('android:id/tabs') elemet.find_element_by_class_name('android.widget.FrameLayout').click()
運行會你會發現不報錯,可也不會點擊,這個是爲何呢?由於在父節點下的全部子節點他的className都是「android.widget.FrameLayout」,這種狀況下他怎麼去點擊操做呢?因此在這種狀況下會引起一個新的定位問題,就是咱們接下來要講的List定位
List故名思義就是一個列表,那麼他的個數也就成了不肯定性,因此這裏須要用複數,因此在咱們定位時咱們不可以接着用find_element_by_id等等定位方式了,咱們須要用他的複數形式find_elements_by_id,全部的定位方式都同樣須要採用複數加s。
以上面例子爲例,我要點擊‘好看視頻’,代碼以下:
elemet =driver.find_element_by_id('android:id/tabs') elemets=elemet.find_elements_by_class_name('android.widget.FrameLayout') elemets[1].click()
運行結果以下:
在web自動化中咱們會碰見frame的問題,在碰見這些內嵌的標籤後咱們須要作的就是切換窗口,那麼在app自動化測試也有相似的狀況就是咱們常常看見的內嵌html,在咱們原生的app中增長一個由html作成的頁面
後續補充,只要在測試以前加這個代碼便可
#獲取當前頁面全部的contexts webview = driver.contexts #在獲取到的contexts list裏面去挨個循環 for context in webview: #判斷循環中單個的context是不是webview,若是是就進行切換,而且跳出循環 if 'WEBVIEW' in context: driver.switch_to.context(context) break
在app自動化中咱們常常會碰見一個問題,咱們須要查找的元素不在當前可展現的屏幕,至於在什麼地方咱們不知道,若是這個時候咱們一直使用在當前頁面查找,那麼系統就會報錯,爲了解決這個問題咱們就須要使用滑動查找。
首先的思路是咱們在須要查找對象的頁面查找一下該元素,判斷該元素是否在當前頁面,若是該元素不在該頁面那麼咱們就須要去互動屏幕,到咱們的下一屏幕,而後再進行查找,依次類推到找到爲止。
方式咱們有了,那麼咱們就須要知道實現這個功能應該有哪些點。下面跟着我一塊兒來分析一下:
一、須要查找的元素咱們是否是須要知道是什麼呢?這個須要先肯定
二、咱們須要找的頁面是在咱們的當前頁面的上方仍是下方仍是左方仍是右方,咱們不能肯定,那麼咱們是否須要肯定咱們須要滑動的方向?
三、元素和方向有了,可是你知道咱們每次須要滑動屏幕的多少嗎?那麼咱們是否須要先去獲取屏幕的大小,而後針對不一樣的方向去計算一個滑動的值呢?
class BaseOperate(object): def __init__(self,driver): self.driver =driver self.get_size() def get_size(self): self.width = self.driver.get_window_size()['width'] self.height = self.driver.get_window_size()['height'] def swipe_left(self,t): self.driver.swipe(self.width*9/10,self.height/2,self.width/10,self.height/2,t) self.screenshot() def swipe_right(self,t): self.driver.swipe(self.width/10,self.height/2,self.width*9/10,self.height/2,t) self.screenshot() def swipe_up(self,t): self.driver.swipe(self.width/2,self.height*9/10,self.width/2,self.height/10,t) self.screenshot() def swipe_down(self,t): self.driver.swipe(self.width/2,self.height/5,self.width/2,self.height*9/10,t) self.screenshot() def findLocal(self): x = 1 while x==1: if self.fact() == 1: self.swipe_up(2000) time.sleep(3) self.fact() else: print ("找到了") x=2 def fact(self): n =1 try: self.driver.find_element_by_id('cn.com.open.mooc:id/tv_replace').click() except Exception,e: return n