如文章《Appium基於安卓的各種FindElement的控件定位方法實踐》所述,Appium擁有眾多獲取控件的方法。當中一種就是依據控件所在頁面的XPATH來定位控件。
本文就是嘗試通過自己的試驗來嘗試對Appium怎樣用xpath來定位控件做一個闡述,其中如有不正確的地方敬請大家指出。
1. 背景
本文嘗試使用的試驗對象是SDK自帶的NotePad應用實例。如果已經有兩個Notes各自是“note1”和“note2”加入到Notepad上面。我們要做的就是嘗試用xpath的方法來定位“note2”這個ListView以下的TextView控件。
注意界面上有3個TextView類型的控件:
- 最上面的作為整個ListView的Title文本為“Notes”的TextView,Index為0
- 中間的文本為“note2”的TextView,Index也是0
- 最以下的文本為“note1”的TextView。Index是1

2. xPath獲取控件方式
2.1 通過推斷控件屬性獲取控件
控件的全部屬性都能夠用作推斷,比方它的text,index。resource-id是否clickable等,比如:
2.1.1 通過文本查找目標控件
el = driver.findElementByXPath("//android.widget.TextView[contains(@text,'note2')]"); assertThat(el.getText(),equalTo("note2"));
2.1.2 通過index查找目標控件
假設我們像以下的方式使用index為0來查找控件note2,那么將會失敗。由於該xpath僅僅是說“我要查找頁面上android.widget.TextView類型的index為0的控件“,但如背景所說我們其實有3個TextView控件。當中最上面的和中間的控件他們的Index都是0.所以終於獲得的控件其實是Appium第一個找到的最上面文本為”Notes“的TextView。el = driver.findElementByXPath("//android.widget.TextView[contains(@index,0)]"); assertThat(el.getText(),equalTo("note2"));那么我們就要想辦法加多點路徑,讓xpath能分辨出須要的是以下的index為0的TextView。而不是上面的。觀看上圖的UIAutomatorViewer控件的分層結構,發現這兩個TextView是從LinearLayout開始分叉的。所以我們應該從該路徑開始通過數組下標指定我們須要的是”在LinearLayout以下的第二個FrameLayout以下的ListView以下的Index為0的TextView:
el = driver.findElementByXPath("//android.widget.LinearLayout[1]/android.widget.FrameLayout/android.widget.ListView/android.widget.TextView[contains(@index,0)]"); assertThat(el.getText(),equalTo("note2"));
2.1.3 通過其它屬性查找目標控件
TBD,這些就不一一列舉了,參照以上兩個演示樣例進行實現就能夠了
2.2 通過指定選擇集合的位置獲得控件
依照我的實踐和理解,通過這樣的方式獲取控件是不靠譜的,起碼存在兩個問題。- 問題1:控件在集合中的位置是不可控的。
el = driver.findElementByXPath("//android.widget.TextView[1]"); assertThat(el.getText(),equalTo("note2"));以上的樣例我原意是想把UIAutomatorViewer里面的上中下3個TextView中的中間那個給找出來,但結果返回來給我的確實最上面的那個“Notes”。
- 問題2:通過添加路徑層數限制查找指定元素集合不起效。
el = driver.findElementByXPath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout/android.widget.ListView/android.widget.TextView[0]"); assertThat(el.getText(),equalTo("note2"));以上樣例我本意是想通過添加父路徑的限制來表明“我想要的控件是ListView以下的那兩個TextView控件中的第一個”。但返回給我的是“An unknown server-side error occurred while processing the command",感覺是越界了的樣子。