Selenium Webdriver元素定位的八種常用方式

文章轉載自:http://www.51testing.com/html/27/n-3686927-2.html


4. By.className()
  className屬性是利用元素的css樣式表所引用的僞類名稱來進行元素查找的方法。對於任何HTML頁面的元素來說,一般程序員或頁面設計師會給元素直接賦予一個樣式屬性或者利用css文件裏的僞類來定義元素樣式,使元素在頁面上顯示時能夠更加美觀。一般css樣式表可能會長成下面這個樣子:
  1 .buttonStyle{
  2
  3     width: 50px;
  4
  5     height: 50px;
  6
  7     border-radius: 50%;
  8
  9     margin: 0% 2%;
  10
  11 }
  定義好後,就可以在頁面元素中引用上述定義好的樣式,如下:
  1 <button name="sampleBtnName" id="sampleBtnId" class="buttonStyle">I'm Button</button>
  如果此時我們要通過className屬性來查找該button並操作它的話,就可以使用className屬性了,代碼如下:
  1 public class SearchElementsByClassName{
  2
  3     public static void main(String[] args){
  4
  5         WebDriver driver = new FirefoxDriver();
  6
  7         driver.get("http://www.forexample.com");
  8
  9         WebElement searchBox =  driver.findElement(By.className("buttonStyle"));
  10
  11         searchBox.sendKeys("Hello, world");
  12
  13     }
  14
  15 }
  注意:使用className來進行元素定位時,有時會碰到一個元素指定了若干個class屬性值的“複合樣式”的情況,如下面這個button:<button id="J_sidebar_login" class="btn btn_big btn_submit" type="submit">登錄</button>。這個button元素指定了三個不同的css僞類名作爲它的樣式屬性值,此時就必須結合後面要介紹的cssSelector方法來定位了,稍後會有詳細例子。
  5. By.linkText()
  這個方法比較直接,即通過超文本鏈接上的文字信息來定位元素,這種方式一般專門用於定位頁面上的超文本鏈接。通常一個超文本鏈接會長成這個樣子:
  1 <a href="/intl/en/about.html">About Google</a>
  我們定位這個元素時,可以使用下面的代碼進行操作:
  1 public class SearchElementsByLinkText{
  2
  3     public static void main(String[] args){
  4
  5         WebDriver driver = new FirefoxDriver();
  6
  7         driver.get("http://www.forexample.com");
  8
  9         WebElement aboutLink = driver.findElement(By.linkText("About Google"));
  10
  11         aboutLink.click();
  12
  13     }
  14
  15 }
  6. By.partialLinkText()
  這個方法是上一個方法的擴展。當你不能準確知道超鏈接上的文本信息或者只想通過一些關鍵字進行匹配時,可以使用這個方法來通過部分鏈接文字進行匹配。代碼如下:
  1 public class SearchElementsByPartialLinkText{
  2
  3     public static void main(String[] args){
  4
  5         WebDriver driver = new FirefoxDriver();
  6
  7         driver.get("http://www.forexample.com");
  8
  9         WebElement aboutLink = driver.findElement(By.partialLinkText("About"));
  10
  11         aboutLink.click();
  12
  13     }
  14
  15 }
  注意:使用這種方法進行定位時,可能會引起的問題是,當你的頁面中不止一個超鏈接包含About時,findElement方法只會返回第一個查找到的元素,而不會返回所有符合條件的元素。如果你要想獲得所有符合條件的元素,還是隻能使用findElements方法。
  7. By.xpath()
  這個方法是非常強大的元素查找方式,使用這種方法幾乎可以定位到頁面上的任意元素。在正式開始使用XPath進行定位前,我們先了解下什麼是XPath。XPath是XML Path的簡稱,由於HTML文檔本身就是一個標準的XML頁面,所以我們可以使用XPath的語法來定位頁面元素。
  假設我們現在以圖(2)所示HTML代碼爲例,要引用對應的對象,XPath語法如下:
  
圖(2)
  絕對路徑寫法(只有一種),寫法如下:
  引用頁面上的form元素(即源碼中的第3行):/html/body/form[1]
  注意:1. 元素的xpath絕對路徑可通過firebug直接查詢。2. 一般不推薦使用絕對路徑的寫法,因爲一旦頁面結構發生變化,該路徑也隨之失效,必須重新寫。3. 絕對路徑以單/號表示,而下面要講的相對路徑則以//表示,這個區別非常重要。另外需要多說一句的是,當xpath的路徑以/開頭時,表示讓Xpath解析引擎從文檔的根節點開始解析。當xpath路徑以//開頭時,則表示讓xpath引擎從文檔的任意符合的元素節點開始進行解析。而當/出現在xpath路徑中時,則表示尋找父節點的直接子節點,當//出現在xpath路徑中時,表示尋找父節點下任意符合條件的子節點,不管嵌套了多少層級(這些下面都有例子,大家可以參照來試驗)。弄清這個原則,就可以理解其實xpath的路徑可以絕對路徑和相對路徑混合在一起來進行表示,想怎麼玩就怎麼玩。
  下面是相對路徑的引用寫法:
  查找頁面根元素://
  查找頁面上所有的input元素://input
  查找頁面上第一個form元素內的直接子input元素(即只包括form元素的下一級input元素,使用絕對路徑表示,單/號)://form[1]/input
  查找頁面上第一個form元素內的所有子input元素(只要在form元素內的input都算,不管還嵌套了多少個其他標籤,使用相對路徑表示,雙//號)://form[1]//input
  查找頁面上第一個form元素://form[1]
  查找頁面上id爲loginForm的form元素://form[@id='loginForm']
  查找頁面上具有name屬性爲username的input元素://input[@name='username']
  查找頁面上id爲loginForm的form元素下的第一個input元素://form[@id='loginForm']/input[1]
  查找頁面具有name屬性爲contiune並且type屬性爲button的input元素://input[@name='continue'][@type='button']
  查找頁面上id爲loginForm的form元素下第4個input元素://form[@id='loginForm']/input[4]
  Xpath功能很強大,所以也可以寫得更加複雜一些,如下面圖(3)的HTML源碼。
  
圖(3)
  如果我們現在要引用id爲“J_password”的input元素,該怎麼寫呢?我們可以像下面這樣寫:
  WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/dl/dt/input[@id='J_password']"));
  也可以寫成:
  WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/*/*/input[@id='J_password']"));
  這裏解釋一下,其中//*[@id=’ J_login_form’]這一段是指在根元素下查找任意id爲J_login_form的元素,此時相當於引用到了form元素。後面的路徑必須按照源碼的層級依次往下寫。按照圖(3)所示代碼中,我們要找的input元素包含在一個dt標籤內,而dt又包含在dl標籤內,所以中間必須寫上dl和dt兩層,纔到input這層。當然我們也可以用*號省略具體的標籤名稱,但元素的層級關係必須體現出來,比如我們不能寫成//*[@id='J_login_form']/input[@id='J_password'],這樣肯定會報錯的。
  前面講的都是xpath中基於準確元素屬性的定位,其實xpath作爲定位神器也可以用於模糊匹配。比如下面圖(4)所示代碼:
  
圖(4)
  這段代碼中的“退出”這個超鏈接,沒有標準id元素,只有一個rel和href,不是很好定位。不妨我們就用xpath的幾種模糊匹配模式來定位它吧,主要有三種方式,舉例如下。
  a. 用contains關鍵字,定位代碼如下:
  1 driver.findElement(By.xpath(“//a[contains(@href, ‘logout’)]”));
  這句話的意思是尋找頁面中href屬性值包含有logout這個單詞的所有a元素,由於這個退出按鈕的href屬性裏肯定會包含logout,所以這種方式是可行的,也會經常用到。其中@後面可以跟該元素任意的屬性名。
  b. 用start-with,定位代碼如下:
  1 driver.findElement(By.xpath(“//a[starts-with(@rel, ‘nofo’)]));
  這句的意思是尋找rel屬性以nofo開頭的a元素。其中@後面的rel可以替換成元素的任意其他屬性。
  c. 用Text關鍵字,定位代碼如下:
  1 driver.findElement(By.xpath(“//*[text()=’退出’]));
  這個方法可謂相當霸氣啊。直接查找頁面當中所有的退出二字,根本就不用知道它是個a元素了。這種方法也經常用於純文字的查找。
  另外,如果知道超鏈接元素的文本內容,也可以用
  1 driver.findElement(By.xpath(“//a[contains(text(), ’退出’)]));
  這種方式一般用於知道超鏈接上顯示的部分或全部文本信息時,可以使用。
  最後,關於xpath這種定位方式,webdriver會將整個頁面的所有元素進行掃描以定位我們所需要的元素,所以這是一個非常費時的操作,如果你的腳本中大量使用xpath做元素定位的話,將導致你的腳本執行速度大大降低,所以請慎用。
  8. By.cssSelector()
  cssSelector這種元素定位方式跟xpath比較類似,但執行速度較快,而且各種瀏覽器對它的支持都相當到位,所以功能也是蠻強大的。
  下面是一些常見的cssSelector的定位方式:
  定位id爲flrs的div元素,可以寫成:#flrs     注:相當於xpath語法的//div[@id=’flrs’]
  定位id爲flrs下的a元素,可以寫成 #flrs > a  注:相當於xpath語法的//div[@id=’flrs’]/a
  定位id爲flrs下的href屬性值爲/forexample/about.html的元素,可以寫成: #flrs > a[href=”/forexample/about.html”]
  如果需要指定多個屬性值時,可以逐一加在後面,如#flrs > input[name=”username”][type=”text”]。
  明白基本語法後,我們來嘗試用cssSelector方式來引用圖(3)中選中的那個input對象,代碼如下:
  WebElement password = driver.findElement(By.cssSelector("#J_login_form>dl>dt>input[id=’ J_password’]"));
  同樣必須注意層級關係,這個不能省略。
  cssSelector還有一個用處是定位使用了複合樣式表的元素,之前在第4種方式className裏面提到過。現在我們就來看看如何通過cssSelector來引用到第4種方式中提到的那個button。button代碼如下:
  <button id="J_sidebar_login" class="btn btn_big btn_submit" type="submit">登錄</button>
  cssSelector引用元素代碼如下:
  driver.findElement(By.cssSelector("button.btn.btn_big.btn_submit"))
  。這樣就可以順利引用到使用了複合樣式的元素了。
  此外,cssSelector還有一些高級用法,如果熟練後可以更加方便地幫助我們定位元素,如我們可以利用^用於匹配一個前綴,$用於匹配一個後綴,*用於匹配任意字符。例如:
  匹配一個有id屬性,並且id屬性是以”id_prefix_”開頭的超鏈接元素:a[id^='id_prefix_']
  匹配一個有id屬性,並且id屬性是以”_id_sufix”結尾的超鏈接元素:a[id$='_id_sufix']
  匹配一個有id屬性,並且id屬性中包含”id_pattern”字符的超鏈接元素:a[id*='id_pattern']
  最後再總結一下,各種方式在選擇的時候應該怎麼選擇:
  1. 當頁面元素有id屬性時,最好儘量用id來定位。但由於現實項目中很多程序員其實寫的代碼並不規範,會缺少很多標準屬性,這時就只有選擇其他定位方法。
  2. xpath很強悍,但定位性能不是很好,所以還是儘量少用。如果確實少數元素不好定位,可以選擇xpath或cssSelector。
  3. 當要定位一組元素相同元素時,可以考慮用tagName或name。
  4. 當有鏈接需要定位時,可以考慮linkText或partialLinkText方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章