在第一篇文章中,成功用的Postman模拟了打开了一个百度地址,这章主要是记录Selenium中我们最常基础方法了 - 定位元素。
我们可以看到selenium-api下By这个类当中 包含了常用的寻元素内部静态类,这些内部类都满足
- 继承与By这个类,
- 实现序列化的接口(没有过多研究,可以查看更多信息)
1.首先把几个基础的概念放在前面:
- SearchContext:WebElement和WebDriver都实现了接口中的两个方法 findElement / findElements。
- WebElement和WebDriver都需要实现以下的接口,他们的寻找元素的方法会不一样,
- WebElement中的寻元素方法命令的类型是 FIND_CHILD_ELEMENT 而不是FIND_ELEMENT,同时接口的地址也会不一样(需要带上element的id)
2.接下来我们debug WebElement e = c.findElement(By.id("kw")); 这行代码,可以看到它的调用的顺序
以下是具体的调用顺序:
// 调用WebDriver中的findElement方法
public WebElement findElement(By by) {
return by.findElement(this);
}
// 调用ById.findElement的方法, context是Webdriver,那么调用
@Override
public WebElement findElement(SearchContext context) {
// 因为webDriver实现了FindsById接口,所以调用webDriver.findElementById方法
if (context instanceof FindsById)
return ((FindsById) context).findElementById(id);
return ((FindsByXPath) context).findElementByXPath(".//*[@id = '" + id
+ "']");
}
// 调用webDriver.findElementById
public WebElement findElementById(String using) {
return findElement("id", using);// 此处的字符串id 在后面的request封装时要用
}
//调用webDriver中的findElement方法
protected WebElement findElement(String by, String using) {
if (using == null) {
throw new IllegalArgumentException("Cannot find elements when the selector is null.");
}
// 这行代码将command和附带的参数转换成httprequest 并返回一个WebElement对象
Response response = execute(DriverCommand.FIND_ELEMENT,
ImmutableMap.of("using", by, "value", using));
Object value = response.getValue();
WebElement element;
try {
element = (WebElement) value;
} catch (ClassCastException ex) {
throw new WebDriverException("Returned value cannot be converted to WebElement: " + value, ex);
}
setFoundBy(this, element, by, using);
return element;
}
3.通过日志查询我们可以看到返回的内容
4.其他寻元素方法也是同理,只是在execute的时候封装了不同的json格式的数据 放在request里面。
至于RemoteWebElement中的findElement方法,其实只是在uri中加了一个元素的id(用于限制寻元素的范围。
public WebElement findElement(By by) {
return by.findElement(this);
}
protected WebElement findElement(String using, String value) {
// 需要加上id这个属性(也就是我们在找到一个元素时 他们返回的元素ID标识
Response response = execute(DriverCommand.FIND_CHILD_ELEMENT,
ImmutableMap.of("id", id, "using", using, "value", value));
Object responseValue = response.getValue();
WebElement element;
try {
element = (WebElement) responseValue;
} catch (ClassCastException ex) {
throw new WebDriverException("Returned value cannot be converted to WebElement: " + value, ex);
}
parent.setFoundBy(this, element, using, value);
return element;
}
总结:
- 所有的寻元素的 *** 作都是通过封装成request并且到这个接口。
- 我们可以看到 locator 的策略只有5种,其中ById ByClassName ByName其实在实质上都是使用的css selectors 策略,只是selenium会帮我们转化成css 选择器的格式,比如用id kw找元素时,会变成#kw
- FindElements 和FindElement的原理相同,只是接口不同,不再赘述
- Command和接口地址对应除了看官方文档也可以查看包中这个类,里面定义了接口的方法,地址,占位符等信息。WebDriverhttps://www.w3.org/TR/webdriver1/
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)