记录自己看selenium源码的一些收获(三) - By之定位元素

在第一篇文章中,成功用的Postman模拟了打开了一个百度地址,这章主要是记录Selenium中我们最常基础方法了 - 定位元素。


我们可以看到selenium-api下By这个类当中 包含了常用的寻元素内部静态类,这些内部类都满足

  1. 继承与By这个类,
  2. 实现序列化的接口(没有过多研究,可以查看更多信息)

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的原理相同,只是接口不同,不再赘述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值