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

 

  1. 概要

在使用Webtest测试过程中,我们大部分情况根据录制的map文件定位元素。 但是当我们遇到很多由于环境原因录制map决绝不了的问题时,我们可以考虑下一下定位方式。

Map录制导致不能使用的情况大概分为:

菜单栏,由于安装不同的组件导致录制的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;

}

 

猜你喜欢

转载自blog.csdn.net/xiaoguanyusb/article/details/82143753