1.什麼是XPathhtml
XPath定位方式是自動化測試定位技術中的必殺技,幾乎能夠解決全部的定位難題。它是XML Path語言的縮寫,主要用於在XML 文檔中選擇文檔中的節點。基於XML樹狀文檔結構,XPath語言能夠用於在整顆樹中尋找指定的節點。因爲網頁的HTML代碼是一種特殊的XML文檔,所以XPath也支持在HTML代碼中定位HTML樹狀文檔結構中的節點。它是一種選擇器,在firefox中用firepath可查看。ide
2.XPath語法函數
被測試網頁的HTML代碼(xPathDemo.html下載)測試
<html> <body> <div id="div1"> <input name="div1input"></input> <a href="http://www.sogou.com">搜狗搜索</a> <img alt="div1-img1" src="http://www.sogou.com/images/logo/new/sogou.png" href="http://www.sogou.com">搜狗圖片</img> <input type="button" value="查詢" /> </div> <br/> <div name="div2"> <input name="div2input"></input> <a href="http://www.baidu.com">百度搜索</a> <img alt="div2-img" src="http://www.baidu.com/img/bdlogo.png" href="http://www.baidu.com">百度圖片</img> </div> </body> </html>
(1)使用絕對路徑來定位元素spa
例:在被測試網頁中,查找第一個div標籤中的按鈕。firefox
Java定位語句:WebElement button=driver.findElement(By.xpath("/html/body/div/input[@value='查詢']")); code
代碼解釋:/表示根目錄,絕對路徑。該表達式從HTML代碼的最外曾節點逐層查找,最後定位到按鈕節點。htm
說明:使用絕對路徑定位方式的好處在於能夠驗證頁面是否發生變化。若是頁面發生變化,通常會形成原有定位成功的XPaht表達式定位失敗,由此可發現網頁結構發生了改變。使用絕對路徑定位是十分脆弱的,由於即使頁面代碼發生了微小的變化,也會形成原有的XPath表達式定位失敗。在自動化測試的定位中,優先推薦使用相對路徑定位方式。blog
(2)使用相對路徑來定位元素索引
例:在被測試網頁中,查找第一個div標籤中的按鈕。
Java定位語句:WebElement button=driver.findElement(By.xpath("//input[@value='查詢']"));
代碼解釋:XPath表達式中的「//」表示在HTML文檔的所有層級位置進行查找,input[@value="查詢"]表示定位顯示「查詢」兩個字的按鈕。
說明:相對路徑的XPath表達式更簡潔,無論頁面發生了何種變化,只要input的value值是「查詢」兩個字就能夠被定位到。推薦使用相對路徑的XPath表達式,可大大下降測試腳本中定位表達式的維護成本。
(3)使用索引號進行定位
例:在被測試網頁中,查找第二個div標籤中的「查詢」按鈕。
XPath表達式://input[2]
代碼解釋:根據元素類型在頁面中出現的前後順序,可使用序號來查找指定的頁面元素。本實例的XPath表達式表示查找頁面中第二個出現的input元素,即被測試頁面上的按鈕元素。
說明:若是使用「//input[1]」,會定位到兩個輸入框元素,由於每一個div裏面均包含input元素,XPath在查找的時候把每一個div節點看成相同的起始層級開始查找,因此使用「//input[1]」表達式會同時查找到兩個div節點中的第一個input元素。所以在使用序號進行頁面定位元素的時候,須要注意網頁HTML代碼中是否包含多個層級徹底相同的代碼結構,若包含多個則會定位到多個頁面元素。
若頁面元素常常被發現新增或者減小的狀況,不建議使用索引號定位的方式,由於頁面變化極可能會讓使用索引號的XPath表達式定位失敗。
(4)使用頁面元素的屬性值定位元素實例
在定位頁面元素的時候,會遇到各類複雜結構的網頁,而且常常出現沒法使用ID、name方式定位的狀況。若不想使用絕對路徑的定位方式,又搞不清楚到底使用什麼序號來定位頁面元素,那麼推薦使用屬性值定位元素的方式。
例:嘗試定位被測試網頁中的第一個圖片元素。
Java定位語句:WebElement img=driver.findElement(By.xpath("//img[@alt='div1-img1']"));
代碼解釋:表達式使用了相對路徑定位方式,而且使用了圖片的alt屬性值來進行定位,經過查看頁面的HTML代碼可獲取圖片的alt值。
說明:被測試網頁的元素一般會包含各類各樣的屬性值,而且不少屬性值具備惟一性。若能確認屬性值發生變動的可能性很低且具備惟一值,強烈建議使用相對路徑方式結合屬性值定位的方式來編寫XPath定位表達式,基於此定位方法可解決99%的頁面元素定位難題。
練習:試着去說出下面的定位元素:
(5)使用模糊的屬性值定位元素
在自動化測試的實施過程當中,會遇到另一種狀況:頁面元素的屬性值會被動態地生成,即每次看到的頁面元素屬性值是不同的,此類頁面元素會加大定位難度,使用模糊的屬性值定位方式可解決一部分此類難題。XPath函數可實現模糊屬性值的定位需求。
XPath經常使用函數以下表所示。
XPath函數 | 定位表達式實例 | 表達式解釋 |
Starts-with() | //img[starts-with(@alt,'div1')] | 查找圖片alt屬性開始位置包含"div1"關鍵字的頁面元素 |
Contains() | //img[contains(@alt,'g1')] | 查找圖片alt屬性包含「g1」關鍵字的頁面元素 |
Contains()函數屬於XPath函數的高級用法,使用場景較多,頁面元素的屬性值只要具備固定不變的幾個關鍵字,即便頁面元素的屬性值常常發生必定程度的變化,依舊可使用Contians()函數進行定位。
(6)使用XPath的軸(Axis)進行元素定位
軸可定義相對於當前節點的節點集。使用XPath軸(Axis)方式可依據在文檔樹中的元素相對位置關係進行定位。先找到一個相對好定位的元素,依據它和要定位元素的相對位置進行定位,可解決一些元素難以定位的問題。
語法爲:軸名稱::節點。
XPath軸關鍵字 | 軸的含義說明 | 定位表達式實例 | 表達式解釋 |
parent | 選擇當前節點的上層父節點 | //img[@alt='div2-img2']/parent::div | 查找到alt屬性值爲div2-img的圖片,並基於圖片位置找到它上一級的div頁面元素 |
child | 選擇當前節點的下層子節點 | //div[@id='div1']/child::img | 查找到ID屬性值爲div1的div頁面元素,並基於div的位置找到它下層節點中的img頁面元素 |
ancestor | 選擇當前節點全部上層的節點 | //img[@alt='div2-img2']/ancestor::div | 查找到alt屬性值爲div2-img的圖片,並基於圖片位置找到它上級的div頁面元素 |
descedant | 選擇當前節點全部下層的節點 | //div[@name='div2']/descendant::img | 查找到name屬性值的div頁面元素,並基於div的位置找到它下級全部節點中的img頁面元素 |
following | 選擇在當前節點以後顯示的全部節點 | //div[@id='div1']/following::img | 查找到ID屬性值爲div1的div頁面元素,並基於div的位置找到他後面節點中的img頁面元素 |
following-sibling | 選擇當前節點以後的全部平級節點 | //a[@href='http://www.sogou.com']/following-sibling::input | 查找到連接地址爲http://www.sogou.com的連接頁面元素,並基於連接的位置找到它同級節點中的input頁面元素 |
preceding | 選擇當前節點前面的全部節點 | //img[@alt='div2-img2']/preceding::div | 查找到alt屬性值爲div2-img2的圖片頁面元素,並基於圖片的位置找到它前面節點中的div頁面元素 |
preceding-sibling | 選擇當前節點前面的全部同級節點 | //img[@alt='div2-img2']/preceding-sibling::a[1] | 查找到alt屬性值爲div2-img2的圖片頁面元素,並基於圖片的位置找到它前面同級節點中的第二個連接頁面元素 |
(7)使用頁面元素的文原本定位元素
使用text()函數能夠定位到包含某些關鍵字的頁面元素。
說明:使用文字匹配模式進行定位,爲定位複雜的頁面元素提供了一種強大的定位模式,在遇到定位困難的時候,可優先使用此方法進行定位。建議使用此定位方式進行大量練習,作到可隨意定位到頁面中的任意元素。
3.總結
(1)經常使用符號說明
(2)路徑表達式查看
在網頁元素上,點擊鼠標右鍵,選擇「Inspect in File Path」,可查看某個網頁元素的xpath路徑。例如,定位百度首頁的「新聞」元素。
(3)函數
//div[contains(@id,'in')],表示選擇id中包含有'in'的div節點
<a class="baidu" href="http://www.baidu.com">baidu</a>
查找節點的文本值爲baidu的超連接,//a[text()='baidu']
//input[@name='identity' or @class='Volvo'][last()],取最後一個
//div[starts-with(@id,'in')],表示選擇以id屬性爲'in'開頭的div節點
//input[@name='identity' and not(contains(@class,'A'))],表示匹配出name爲identity而且class的值中不包含A的input節點
//input[not(@id)],匹配出input節點不含有id屬性的節點。
(4)xpath軸練習
以axisDemo2網頁(下載)爲例,進行講解
//div[@id='radio']//label[text()='Saab']/preceding-sibling::input是什麼意思?
//input[following-sibling::label[text()='Saab']]是什麼意思?