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

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

Posted on 2015-01-07 13:00 測試控 閱讀(127913) 評論(9) 編輯 收藏css

樓主原創,歡迎學習和交流,碼字不容易,轉載請註明出處,謝謝。html

在使用selenium webdriver進行元素定位時,一般使用findElement或findElements方法結合By類返回的元素句柄來定位元素。其中By類的經常使用定位方式共八種,現分別介紹以下。程序員

1. By.name()web

假設咱們要測試的頁面源碼以下:瀏覽器

<button id="gbqfba" aria-label="Google Search" name="btnK" class="gbqfba"><span id="gbqfsa">Google Search</span></button>

 

當咱們要用name屬性來引用這個button並點擊它時,代碼以下:ide

複製代碼

1 public class SearchButtonByName {
2         public static void main(String[] args){
3                WebDriver driver = new FirefoxDriver();
4                driver.get("http://www.forexample.com");
5                WebElement searchBox = driver.findElement(By.name("btnK"));
6                searchBox.click();
7         }
8 }

複製代碼

 

2. By.id()post

頁面源碼以下:性能

1 <button id="gbqfba" aria-label="Google Search" name="btnK" class="gbqfba"><span id="gbqfsa">Google Search</span></button>

 

要引用該button並點擊它時,代碼以下:學習

複製代碼

1 public class SearchButtonById {
 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.id("gbqfba"));
10 
11             searchBox.click();
12 
13         }
14 
15 }

複製代碼

 

3. By.tagName()測試

該方法能夠經過元素的標籤名稱來查找元素。該方法跟以前兩個方法的區別是,這個方法搜索到的元素一般不止一個,因此通常建議結合使用findElements方法來使用。好比咱們如今要查找頁面上有多少個button,就能夠用button這個tagName來進行查找,代碼以下:

複製代碼

public class SearchPageByTagName{

     public static void main(String[] args){

            WebDriver driver = new FirefoxDriver();
            driver.get("http://www.forexample.com");
            List<WebElement> buttons = driver.findElements(By.tagName("button"));

            System.out.println(buttons.size());  //打印出button的個數

    }

}

複製代碼

 

另外,在使用tagName方法進行定位時,還有一個地方須要注意的是,一般有些HTML元素的tagName是相同的,以下圖(1)所示。

 

圖(1)

 

從圖中咱們能夠看到,單選框、複選框、文本框和密碼框的元素標籤都是input,此時單靠tagName沒法準確地獲得咱們想要的元素,須要結合type屬性才能過濾出咱們要的元素。示例代碼以下:

複製代碼

1 public class SearchElementsByTagName{
 2 
 3         public static void main(String[] args){
 4 
 5             WebDriver driver = new FirefoxDriver();
 6 
 7             driver.get("http://www.forexample.com");
 8 
 9             List<WebElement> allInputs = driver.findElements(By.tagName("input"));
10 
11             //只打印全部文本框的值
12 
13             for(WebElement e: allInputs){
14 
15                   if (e.getAttribute(「type」).equals(「text」)){
16 
17                   System.out.println(e.getText().toString());  //打印出每一個文本框裏的值
18 
19                   }
20 
21             }
22 
23        }
24 
25 }

複製代碼

 

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方式。

相關文章
相關標籤/搜索