1. 程式人生 > >selenium webdriver 深入理解各元素定位方法

selenium webdriver 深入理解各元素定位方法

  1. 概要

選單欄,由於安裝不同的元件導致錄製的xpath發生變化。

左側樹,由於左側樹由於業務會經常發生變動,導致錄製xpath發生變化。

列表資訊,通常一個列表裡面包含N多資料,我們不可以挨個去錄製。且列表一般都是可配置列的。

動態id,很多彈出頁面,彈出框之類的頁面大多都使用的是動態id

為解決此類問題,我們要學會活用selenium為我們提供的多種定位方式。 用以達到用例穩定執行的目標。

  • By.id(id)、By.xpath(xpath);使用最多的定位方式
  • By.linkText(linkText),By.partialLinkText(linkText)  a標籤的不二之選
  • By.tagName(name) 特別好用的定位方式
  • By.className(className)可以解決很大的問題
  • By.cssSelector(selector) 超級無敵好用
  1. 使用最多的定位方式By.id(id)、By.xpath(xpath)

By.id定位是最高效也是首選的方法用於查詢一個元素。UI 開發人員常犯的錯誤是,要麼沒有指定id,要麼自動生成隨機 id,這兩種情況都應避免。及時是使用 class 也比使用自動生成隨機 id要好的多。

HTML:

<div id="coolestWidgetEvah">...</div>

Java:

WebElement element = driver.findElement(By.id("coolestWidgetEvah")); 

By xpath: 在沒有id的場景中。 最常用的是xpath。無所不能的定位方式。 類似如下所示。

定點陣圖片:

    xpath=//img[@alt='image alt text goes here']

定位表格:

    xpath=//table[@id='table1']//tr[4]/td[2]
                 xpath=(//table[@class='nice'])//th[text()='headertext']/

定位a標籤

    xpath=//a[contains(@href,'href goes here')]
                 xpath=//a[contains(@href,'#id1')]/@class

定位input

    xpath=//input[@name='name2' and @value='yes']

 Java:

WebElement element = driver.findElement(By.xpath(xpath));

  1. 被遺忘的定位方式:
  1. By.linkText,By.partialLinkText a標籤的不二之選

By Link Text :查詢連結文字匹配的連結元素。

HTML:

<a href="http://www.google.com/search?q=cheese">cheese</a>>

Java:

WebElement cheese = driver.findElement(By.linkText("cheese"));

By Partial Link Text:查詢連結文字部分匹配的連結元素。

HTML:

<a href="http://www.google.com/search?q=cheese">search for cheese</a>>

Java:

WebElement cheese = driver.findElement(By.partialLinkText("cheese"));

在我們http://www.seleniumeasy.com/test/頁面為例:

例如: 點選報表列表。

點選選單:

我們通過直接錄製點選報表的形式因為安裝的控制元件原因會導致xpath等發生變化導致定位失敗。

此時我們若使用類似如下方法, 將使用By.partialLinkText(reportmenu)的方式直接點選選單名稱。 會很大程度提升用例的穩定性。

public void clickMenu(String reportmenu) {

drivre.findElement(By.partialLinkText(reportmenu)).click();

}
  1. By.tagName特別好用的定位方式

By Tag Name 是一個特別好用的定位方式。 多用於都配合driver.findElements(By.tagName(name))使用。

例如:

 下拉框:

列表:

樹形選單:

如上圖所示:

當我們需要處理類似多種資料時。 比如我們需要遍歷下拉列表。 遍歷獲取列表框中的資料。 點選樹狀選單時。           此時通過 By Tag Name 是最好的選擇方式。

如下程式碼,我們首先定位到下拉列表框。 然後通過By.tagName("div")),獲取自稱元素。

再通過element.findElements(By.tagName("div")) 的方式獲取我們所需要的所有的列表數值。

後續我們通過傳入的引數進行操作。  可以達到整個版本通用。

public static void selectByVisibleText(WebDriver driver, String visibleText) {

WebElement element = driver.findFirstElement(By.tagName("div"));

List<WebElement> elementList = element.findElements(By.tagName("div"));

logger.info("elementList.size():" + elementList.size());



for (WebElement webElement : elementList) {

String text = webElement.getText();

logger.info("text:" + text);

if (visibleText != null && text.contains(visibleText)) {

BasicAction.sleep(1);

webElement.click();

break;

}

}

}

當我們處理list列表的時候,只需要獲取到table的元素。 然後通過By.tagName("tr")) 獲取行元素

再通過By.tagName("td"))獲取列元素。

通過行列的兩層遍歷便可得到整個列表的元素資訊。

public static JSONArray getListInfo(WebElemnt table) {

JSONObject object = new JSONObject();

JSONArray array = new JSONArray();

List<WebElement> rows = table.findElements(By.tagName("tr"));

// logger.info("rows size: " + rows.size());

for (WebElement row : rows) {

if (row.getAttribute("class").contains("eview-table-tr")) {

List<WebElement> cols = row.findElements(By.tagName("td"));

if (cols.size() == 1) {

break;

} else {

for (WebElement col : cols) {

object.put(col.getAttribute("data-colid"), col.getText());

}

array.add(object);

}

}

}

return array;

}
  1. By.className可以解決很大的問題

如下所示,我們需要獲取彈出框中的提示資訊時。 當前頁面彈出框 沒有其他可定位的條件。 此時通過唯一的className定位是極好的。

 public static String getMsgDialogText() {

WebDriver driver ;

String text = driver.findElement(By.className("eview-msg-content")).getText();

logger.info("MessageDialog Text:" + text);

return text;

}
  1. By.cssSelector超級無敵好用

定位類似標籤頁中有多個class的。  此時我們使用className定位不都準確。可以使用css的定位方式處理。

public static JSONObject getPortalNameJson(WebElement chartElement) {

JSONObject object = new JSONObject();

WebElement yElement = chartElement.findElement(By.cssSelector(".dual-list list-left.col-md-5"));

List<WebElement> divElements = yElement.findElements(By.className("list-group-item"));

Map<String, String> deviceMap = new LinkedHashMap<String, String>();

Map<String, String> devicePointMap = new LinkedHashMap<String, String>();

for (WebElement webElement : divElements) {

String title = null;

title = webElement.getText();

if (title.endsWith("...")) {

title = webElement.getAttribute("title");

title = "..." + title;  //表示該裝置名稱未全部顯示

}

String index = webElement.getAttribute("index");

String namePoint = webElement.getLocation().toString();

devicePointMap.put(title, namePoint);

deviceMap.put(index, title);

}

object.put(NAME_MAP, deviceMap);

object.put(NAME_POINT_MAP, devicePointMap);

logger.info("getPortalNameJson object: " + object);

return object;

}