天天看點

appium元素定位(12)

自動化測試來說,核心技能就是對象的定位。不管是 web 頁面上的一個

按鈕或輸入框,還是移動 app 上的一個按鈕或輸框,我們要想對其進行點選或輸入操作,前提是要先找到這個對象。對于手工測試來說,是由測試人員來完人了,人通過眼睛與大腦來識别一個按鈕或輸入框,但自動測試工具沒有這種能力,但是一個對象一定會有一些屬性(如 id、class 等),自動化測試工具就是靠着這些屬性來識别和查找對象。webdriver 提供了八種元素定位方法:

l id

l name

l class name

l tag name

l link text

l partial link text

l xpath

l css selector

在 Python 語言中對應的定位方法如下:

find_element_by_id()

find_element_by_name()

find_element_by_class_name()

find_element_by_tag_name()

find_element_by_link_text()

find_element_by_partial_link_text()

find_element_by_xpath()

find_element_by_css_selector()

一組元素定位的方法如下:

find_elements_by_id()

find_elements_by_name()

find_elements_by_class_name()

find_elements_by_tag_name()

find_elements_by_link_text()

find_elements_by_partial_link_text()

find_elements_by_xpath()

find_elements_by_css_selector()

Appium 完全繼承了 WebDriver 中所定義的這些方法,除此之外對其進行了擴充,以便适合移動端對象的定位與操作 

定位的工具

uiautomatorviewer:Android SDK自帶的一個工具,在tools目錄下

monitor:Android SDK自帶的一個工具,在tools目錄下

Appium Inspector:Appium自帶的一個功能,隻有mac下可以使用該功能

定位詳解

通過id定位

(取resource-id的值):

driver.find_element_by_id("com.wuba.zhuanzhuan:id/azo")

也可以直接用id後面的内容driver.find_element_by_id("azo")

通過class_name定位

(取class的内容)

driver.find_element_by_class_name("android.widget.RelativeLayout")

通過xpath定位

(取xpath得内容)

driver.find_element_by_xpath("//android.widget.LinearLayout[1]/android.widget.XXX")

通過text定位

(需要使用uiautomator的定位方式,使用text的内容)

driver.find_elements_by_android_uiautomator("new UiSelector().text(\"+關注\")")

使用這裡需要注意一下,通過text定位的結果是個list,不能直接click。是以如果要點選需要取數組的值,比如下面是點選找到的第一個元素

driver.find_elements_by_android_uiautomator("new UiSelector().text(\"+關注\")")[0].click()

通過css_selector定位(webview)

隻适用于webview的html頁面,繼承自webdriver,與pc版本的UI測試一緻

driver.find_element_by_css_selector()

通過link_text定位(webview)

隻适用于webview容器中的html頁面,繼承自webdriver,與pc版本的UI測試一緻

driver.find_element_by_link_text()

通過name定位

web view容器中的html頁面可以用name定位,native并沒有name屬性

driver.find_element_by_name()

2.定位元素的另一種寫法:find_element(by,value)

find_element_by_方式(value)實際調用的都是find_element(by,value)

需要導入這個包:from selenium.webdriver.common.by import By

例如:定位id為ag2的元素

方式一:driver.find_element_by_id("ag2”)

方式二:driver.find_element(By.ID,"ag2")

這個操作的好處是可以直接把操作的by和value放到一個元組裡,然後調用通用方法來傳參獲得元素結果

cateid=(By.ID,"ag2")

driver.find_element(*cateid).click()

by的操作可以是:

By.ID   相當于by_id

By.CLASS_NAME  相當于by_class_name

By.XPATH   相當于by_xpath

By.NAME   相當于by_name

By.TAG_NAME   相當于by_tag_name

By.CSS_SELECTOR  相當于by_css_selector

By.LINK_TEXT  相當于by_link_text

3.find_elements_by_定位方式(value)傳回元素數組

用法與find_element_by_方式(value)一緻,但是傳回一個數組。可以通過數組的索引來通路具體的某個結果

例如:通過class_name定位到多個元素,我想點選第一個元素

driver.find_elements_by_class_name("android.widget.RelativeLayout”)[0].click()

4.傳回元素數組的另一種寫法:find_elements(by,value)

用法與find_element(by,value)一緻,但是傳回一個數組。可以通過數組的索引來通路具體的某個結果

例如:通過class_name定位到多個元素,我想點選第一個元素

driver.find_elements(By.CLASS_NAME,"android.widget.RelativeLayout”)[0].click()

5.通過元素定位元素

可以先找到某個元素,然後再進一步定位元素

find_element_by_class_xpath(“xxx”).find_element_by_name(“yyy")

UiSelector

  概述:

    按照一定的條件(例如控件的text值,資源id),定位界面上的元素。UiSelector對象的最終目的是去構造一個UiObject對象。

  摘要:

1、根據text構造:

函數傳回值 函數體 說明 用法
UiSelector text(String text) 根據“控件text屬性的内容”構造出UiSelector對象 例如,一個控件text的值是“發現”,UiSelector s = new UiSelector().text("發現");
UiSelector textContains(String text) 根據“控件text屬性包含的内容”構造出UiSelector對象 同上例子:UiSelector s = new UiSelector().textContains("現");
UiSelector textMatches(String regex)  根據“控件text屬性正規表達式的内容”構造出UiSelector對象 正規表達式文法參考網上資料即可。
UiSelector textStartsWith(String text) 根據“控件text屬性開始的内容”構造出UiSelector對象 同上例子:UiSelector s = new UiSelector().textStartsWith("發");

      比較常用,準确度也比較高,中文查找的時候,如果遇到 “UiOjbectNotFoundException” 的時候,記得把項目的編碼格式改為utf-8。

2、根據description構造:

UiSelector description(String desc) 根據“控件content-desc屬性的内容”構造出UiSelector對象
UiSelector descriptionContains(String desc) 包含**
UiSelector descriptionMatches(String regex) 正則
UiSelector descriptionStartsWith(String desc) 以**開始

      同text的用法基本一緻,也是比較靠譜的一種方式。

3、根據資源id:

UiSelector resourceId(String id) 根據資源id擷取對象,例如:UiSelector s = new UiSelector().resourceId("com.tencent.mm:id/b8m")
UiSelector resourceIdMatches(String regex) 根據資源id的正規表達式擷取對象

4、根據類:

UiSelector className(String  className):

        根據控件的類名來找到UiSelector對象。

appium元素定位(12)

        但是呢?因為一般Android布局的時候,同樣的控件類名都是一樣的。

        是以我在微信的登入界面調用: UiSelector s = new UiSelector().className("android.widget.TextView") 這句話,它得到的就是我左上開始算第一個class名稱為“android.widget.TextView”的控件。

       

UiSelector instance (int instance):

        上面提到的假如我們想擷取螢幕上電話号碼的那個TextView使用這樣方法,就可以使用instance:

   UiSelector s = new UiSelector().className("android.widget.TextView").instance(1);

UiSelector index(int index):

        用法和上面的instance差不多,谷歌的原文說這個方法是unreliable的,推薦使用instance方法。

UiSelector childSelector(UiSelector selector):

        有的時候假如子控件不好獲得,而其父控件比較好獲得的時候,我們通常采用這樣的方式,例如下面:

appium元素定位(12)

           我們目前選中的是LinearLayout,這個Android中的一種布局,它的裡面嵌套了兩個控件,一個是ImageView,另一個是EditText。這們這裡就通過LinearLayout這個控件找到它的子控件。

        很明顯,父控件id已經給定。我們先得到父控件:UiSelector s_p = new UiSelector().resourceId("com.tencent.mm:id/axj");

        其次 UiSelector s_c= s_p.childSelector( new UiSelector().className("android.widget.EditText") );

        在它的父控件的childSelector方法中傳入一個帶有一定特征的UiSelector對象,即可得到子控件,這裡 s_c 就是輸入框的UiSelector對象。

UiSelector fromParent(UiSelector selector):

        有的時候父控件也不好獲得,而是同級的控件(同屬一個parent)比較好擷取,那麼使用這樣方法,還拿上面的舉例:

        我們先得到EditText的UiSelector對象:UiSelector s1 = new UiSelector().resourceId("com.tencent.mm:id/axc");

        得到和它同樣一個父控件的ImageView的UiSelector對象:UiSelector s2 = fromParent( new UiSelector().className("android.widget.ImageView") );

5、根據特有屬性:

UiSelector checked(boolean val) 根據是否可check來構造出UiSelector對象
UiSelector chickable(boolean val)
UiSelector enabled(boolean val)
UiSelector focusable(boolean val)
UiSelector longClickable(boolean val)
UiSelector scrollable(boolean val)
UiSelector selected(boolean val)

      舉個簡單的例如,假如目前的界面,隻有一個checkbox是勾選狀态,你就可以這樣得到:UiSelector s2 = new UiSelector().checked(true)