這篇文章介紹selenium web driver中的xpath定位器。首先先詳細介紹一下什么是xpath以及它的用法。xpath是xml path的簡稱,是一種尋找網(wǎng)頁元素的語言。xml文件大家都見過吧,就長這個樣子:
xml是一種結(jié)構(gòu)化的語言,你看,文件上的信息錯落有致,清楚明白地告訴我們書店里有兩本書,一本是J.K.羅琳的《哈利波特》,另一本是劉慈欣的《三體》。path是路徑的意思,顧名思義,我可以沿著一條路徑找到我想要的元素。比如我想找《三體》的出版年份,先不考慮語法,那這條路徑就應(yīng)該是bookstore -> book[2] -> year,[2]代表第二個<book>。
你會發(fā)現(xiàn)網(wǎng)頁html和它很像,也有元素、標簽、值之類的東西,比如下面一段html代碼:
每一個元素都用一個標簽(tag)來表示,之前介紹tagName定位器說過了,我們可以用tagName來定位一個元素。有些元素還有屬性,比如上面的<input>,type/id/name/class/value都是它的屬性。每一個屬性都有屬性值,比如id="username",username就是id的屬性值。如果一個元素有id、name、class這種屬性,那我們完全可以直接使用相關(guān)的定位器即可。但如果沒有,比如<input type="submit" class="t1" value="login">這句,xpath就可以派上用場了,因為html也可以按照xml的路徑法則來尋找元素。
xpath路徑分兩種,一種是絕對路徑,另一種是相對路徑。絕對路徑和相對路徑這個概念大家也應(yīng)該聽到過,絕對路徑指的是某一個資源的完整路徑,比如你在C盤的films文件夾中存了一個叫video.avi的視頻文件,這個文件的絕對路徑就是C:\films\video.avi。對于html文檔也一樣
,某一個節(jié)點的絕對路徑是從<html>開始一直到該節(jié)點,比如要找上面的<form>,xpath就是
絕對路徑的起始標識符是“/”,但也可以出現(xiàn)在中間。最一開始的“/”指的是html文檔本身,意思是在當前的html文檔查找;中間的“/”指的是以當前節(jié)點為參照往下找第一層匹配對象。咱們還沒講軸定位,現(xiàn)在只限于向下查找,下篇學了軸定位還可以向上查找或是同層查找,咱們暫時先不考慮。所以,這個xpath的執(zhí)行過程就是:html文檔最開始的節(jié)點是<html>。以<html>為參照查看下面第一層有沒有<body>,發(fā)現(xiàn)有,跳到<body>,這樣<body>就成為了新的當前節(jié)點。接下來再以<body>為參照查找下面第一層看有沒有<div>,發(fā)現(xiàn)有,然后又跳到<div>,這樣<div>又成了新的當前節(jié)點。最后跳到<form>,就是這么一個簡單的過程,永遠都是以當前節(jié)點為參照。如果中間無法找到某個節(jié)點則證明xpath有錯。注意,僅限于下面第一層,你寫/html/form就找不到,因為form不是html的下面第一層,中間隔了body和div兩層。
同理,<input>標簽的絕對路徑就是
總共可以找到四個input標簽。大家或許也看出來了,絕對路徑有一個很大的弊端,被查找的節(jié)點越深,那它的絕對路徑就越長,這時如果開發(fā)網(wǎng)頁的人稍微變動一下代碼,我們的xpath就很可能出錯以致無法定位元素。所以,我們一般都用相對路徑來定義某個元素的xpath。
相對路徑的意思是以當前節(jié)點為參照往下查找所有的指定節(jié)點,不局限于第一層。它用“//”作為起始標識符,也可以出現(xiàn)在中間。最一開始的“//”指的是該xpath會是一個相對路徑,并且在當前的html文檔查找。比如還是尋找<input>,用相對路徑寫xpath就可以直接寫成
簡單吧?意思就是從該html文檔直接查找所有的input。例子中有四對input標簽,都可以被找到。
如果把“//”放在中間,那它指的就是以當前節(jié)點為參照往下找所有匹配對象,不受層級限制,這也就意味著相對路徑不止一種寫法。比如我也可以把尋找input的xpath寫成
翻譯過來就是先從該html文檔直接查找所有body,很明顯例子中只有一對body標簽,直接鎖定。然后再以body為參照查找下面所有的input,有四對input標簽,直接鎖定,定位完成。雖然body和form中間還隔著一層div,但沒關(guān)系,因為“//”不受層次制約。即便四個input不在同一層,只要它們都在body下面,那也都可以找到。比如我改一下html代碼:
把后兩個input從form中挪出去,你寫//body//input還是可以找到所有的input。
需要注意的是,相對路徑里也可以有“/”。還是尋找<input>,如果我想找上圖form里的兩個input,我可以把xpath寫成
翻譯過來就是先從該html文檔直接查找所有body,然后因為是“/”,所以以body為參照往下找第一層的div,接著又是“//”,再以div為參照查找下面所有的form,最后又是“/”,以form為參照往下找第一層的input,總共有兩個。
xpath還可以加入通配符,用“*”表示,指的是所有節(jié)點,比如說
意思就是先選定div下面第一層的所有節(jié)點,再以所有這些節(jié)點為參照尋找下面第一層的input。顯然,div下面第一層只有form一個節(jié)點,這個星號也就只代表form。再舉一個星號代表多個節(jié)點的例子:
form下面第一層有多個input,這個星號指的就是input。
這就是絕對路徑和相對路徑的基本用法??傊?,相對路徑要比絕對路徑省事得多,而且也更加靈活,出錯率相對低一些。我們寫自動化測試代碼時一般也使用相對路徑寫xpath。
那如果我要找的節(jié)點光憑一個標簽名無法定位呢?比如我們的例子中有四個<input>標簽,我想定位<input type=”submit” class=”t1” value=”login”>,可是這四對<input>都滿足//div/form/input,我怎么區(qū)分呢?總不能都選出來吧?這就需要屬性的幫助了。還是讓form包含四個input:
第一種情況是通過完整的屬性值來區(qū)分,xpath格式如下:
注意,屬性前面有一個“@”符號?,F(xiàn)在我可以把xpath修改成//div/form/input[@value="login"],因為這四者只有第三個的value屬性等于login。同理,每個input其實都可以靠屬性的幫助讓xpath對它們唯一標識:
當然,它們也都可以用id/name/classname定位器來定位,可我們假設(shè)它們不能,只能用xpath。
第二種情況是通過部分的屬性值來區(qū)分,xpath格式如下:
contains是包含、包括的意思。之前介紹java字符串時介紹過一個叫contains的方法,可以用來判斷一個字符串是否包含另外一個字符串。xpath這邊是一個道理,比如一個屬性的屬性值很長,你怕寫錯,就可以用contains。比如密碼旁邊的那個input,你可以寫成:
第三種情況是有時候單憑一個屬性值還不能完全解決問題,比如:
我想找第一行,但你會發(fā)現(xiàn)不管是用type/class/value都不能唯一定位第一行,這時就需要用兩個或兩個以上的屬性共同參與。連接幾個屬性的關(guān)鍵字是AND和OR:
AND是與,代表前后兩者都滿足才可以;OR是或,代表前后兩者只要滿足一個即可。這點和java的邏輯運算符是一致的。顯然,這個例子我們應(yīng)該用AND:
第四種情況是屬性是文本的時候,比如一個鏈接或是一個下拉列表里的文字:
把屬性換成text()就可以了。
第五種情況是可以使用索引下標。比如還是這個例子:
四個input可以這么寫:
注意,索引下標不是相對于整個html來說的,而是相對于某個元素而說的,比如我再次把后兩個input從form中挪出去:
現(xiàn)在如果用索引下標寫這四個input就會變成
form下面有兩個input,沒什么問題??蒬iv容易出錯。雖然div下面總共有四個input,但因為你用的是"/",那就意味著以div為參照找下面第一層的,只有兩個input。但是如果你在div后邊用"http://"就不一樣了,因為是找它下邊所有的:
以div為參照總共有四個地方出現(xiàn)input,索引也要相應(yīng)更改。所以,位置不一樣,目標節(jié)點的上一個元素就不一樣,xpath路徑也就不一樣。路徑都不一樣了自然索引下標就不一樣。
如果上述五種情況都無法完成定位,那還可以用更強大的xpath軸(axes)定位方法,下篇討論。xpath語法不復雜,勤加練習就能快速掌握。網(wǎng)上有很多xpath的練習工具可供選擇,如果你安裝了Firefox瀏覽器,再安裝上firepath插件就可以了。安裝后右鍵點擊目標網(wǎng)頁,再選擇用firepath檢查,就可以彈出firepath窗口。截圖如下:
在xpath框中輸入一個合法的xpath就可以看到目標節(jié)點高亮顯示。
本篇知識點及注意事項:
1. xpath可以使用絕對路徑和相對路徑兩種方法對元素定位,因為絕對路徑又長又丑,所以我們用相對路徑。
2. “/”可以出現(xiàn)在最開始,也可以出現(xiàn)在中間。最一開始的“/”是絕對路徑的標志,指的是html文檔本身,意思是在當前的html文檔查找;中間的“/”指的是以當前節(jié)點為參照往下找第一層匹配對象。
3. “//”可以出現(xiàn)在最開始,也可以出現(xiàn)在中間。最一開始的“//”是相對路徑的標志,意思是在當前的html文檔查找;中間的“//”指的就是以當前節(jié)點為參照往下找所有匹配對象,不受層級限制。
4. xpath可以使用屬性以及一些關(guān)鍵字配合使用。