WebDriver与之前Selenium的js注入实现不同:
Selenium通过JS来定位元素处理元素(基本上所有元素都可以定位到)
WebDriver通过WebDriver API定位处理元素:通过浏览器的native component来实现把WebDriver API的调用转化为浏览器的本地调用(WebDriver能更好的模拟真实的环境,但是无法定位隐藏元素)。

最近比较空闲就仔细看了一下Selenium的源码,因为主要是使用WebDriver所以重点关注了一下WebDriver的工作原理。在前一篇blog里已经解释过了WebDriver与之前Selenium的js注入实现不同,直接利用了浏览器native support来操作浏览器。所以对于不同平台,不同的浏览器,必须依赖一个特定的浏览器的native component来实现把WebDriver API的调用转化为浏览器的native invoke。

在我们new一个WebDriver的过程中,Selenium首先会确认浏览器的native component是否存在可用而且版本匹配。接着就在目标浏览器里启动一整套Web Service,这套Web Service使用了Selenium自己设计定义的协议,名字叫做The WebDriver Wire Protocol。这套协议非常之强大,几乎可以操作浏览器做任何事情,包括打开、关闭、最大化、最小化、元素定位、元素点击、上传文件等等等等。

WebDriver Wire协议是通用的,也就是说不管是FirefoxDriver还是ChromeDriver,启动之后都会在某一个端口启动基于这套协议的Web Service。例如FirefoxDriver初始化成功之后,默认会从http://localhost:7055开始,而ChromeDriver则大概是http://localhost:46350之类的。接下来,我们调用WebDriver的任何API,都需要借助一个ComandExecutor发送一个命令,实际上是一个HTTP request给监听端口上的Web Service。在我们的HTTP request的body中,会以WebDriver Wire协议规定的JSON格式的字符串来告诉Selenium我们希望浏览器接下来做社么事情。

这里笔者初步画了一个图来表示各种WebDriver的工作原理:

从上图中我们可以看出,不同浏览器的WebDriver子类,都需要依赖特定的浏览器原生组件,例如Firefox就需要一个add-on名字叫webdriver.xpi。而IE的话就需要用到一个dll文件来转化Web Service的命令为浏览器native的调用。另外,图中还标明了WebDriver Wire协议是一套基于RESTful的web service。如果不明白什么是RESTful的,可以参见笔者之前另外一篇介绍REST的blog(http://blog.csdn.net/ant_yan/article/details/7963517)

关于WebDriver Wire协议的细节,比如希望了解这套Web Service能够做哪些事情,可以阅读Selenium官方的协议文档, 在Selenium的源码中,我们可以找到一个HttpCommandExecutor这个类,里面维护了一个Map<String, CommandInfo>,它负责将一个个代表命令的简单字符串key,转化为相应的URL,因为REST的理念是将所有的操作视作一个个状态,每一个状态对应一个URI。所以当我们以特定的URL发送HTTP request给这个RESTful web service之后,它就能解析出需要执行的操作。截取一段源码如下:

  1. nameToUrl = ImmutableMap.<String, CommandInfo>builder()
  2. .put(NEW_SESSION, post("/session"))
  3. .put(QUIT, delete("/session/:sessionId"))
  4. .put(GET_CURRENT_WINDOW_HANDLE, get("/session/:sessionId/window_handle"))
  5. .put(GET_WINDOW_HANDLES, get("/session/:sessionId/window_handles"))
  6. .put(GET, post("/session/:sessionId/url"))
  7. // The Alert API is still experimental and should not be used.
  8. .put(GET_ALERT, get("/session/:sessionId/alert"))
  9. .put(DISMISS_ALERT, post("/session/:sessionId/dismiss_alert"))
  10. .put(ACCEPT_ALERT, post("/session/:sessionId/accept_alert"))
  11. .put(GET_ALERT_TEXT, get("/session/:sessionId/alert_text"))
  12. .put(SET_ALERT_VALUE, post("/session/:sessionId/alert_text"))

可以看到实际发送的URL都是相对路径,后缀多以/session/:sessionId开头,这也意味着WebDriver每次启动浏览器都会分配一个独立的sessionId,多线程并行的时候彼此之间不会有冲突和干扰。例如我们最常用的一个WebDriver的API,getWebElement在这里就会转化为/session/:sessionId/element这个URL,然后在发出的HTTP request body内再附上具体的参数比如by ID还是CSS还是Xpath,各自的值又是什么。收到并执行了这个操作之后,也会回复一个HTTP response。内容也是JSON,会返回找到的WebElement的各种细节,比如text、CSS selector、tag name、class name等等。以下是解析我们说的HTTP response的代码片段:

  1. try {
  2. response = new JsonToBeanConverter().convert(Response.class, responseAsText);
  3. } catch (ClassCastException e) {
  4. if (responseAsText != null && "".equals(responseAsText)) {
  5. // The remote server has died, but has already set some headers.
  6. // Normally this occurs when the final window of the firefox driver
  7. // is closed on OS X. Return null, as the return value _should_ be
  8. // being ignored. This is not an elegant solution.
  9. return null;
  10. }
  11. throw new WebDriverException("Cannot convert text to response: " + responseAsText, e);
  12. } //...

相信总结道这里,应该对WebDriver的运行原理应该清楚了!其实挺佩服这一套RESTful web service的设计。感觉封装WebDriver暴露出来的public API还可以更加友好跟强大一点,这次就先总结道这里,会继续分析Selenium源码,继续分享的!

Selenium WebDriver 工作原理的更多相关文章

  1. Selenium webdriver工作原理

    webdriver是以server-client 经典模式设计的 server端可以是任何浏览器作为remote server,职责就是处理client的请求并作出相应操作,response的具体内容 ...

  2. [转载]WebDriver工作原理

    转载自:https://www.cnblogs.com/testermark/p/3546287.html WebDriver的工作原理:  在我们new一个WebDriver的过程中,Seleniu ...

  3. WebDriver工作原理

    http://www.cnblogs.com/timsheng/archive/2012/06/12/2546957.html 通过研究selenium-webdriver的源码,笔者发现其实webd ...

  4. appium ,selenium ,webdriver 运行原理与机制

    做测试开发的童鞋都知道,UI自动化你绕不开selenium, webdrvier, appium框架,那么这三者之间有什么关联,它们的原理是什么呢? 简单来说就是: Selenium2  将浏览器原生 ...

  5. WebDriver 工作原理

    WebDriver是W3C的一个标准,由Selenium主持. 具体的协议标准可以从http://code.google.com/p/selenium/wiki/JsonWireProtocol#Co ...

  6. Selenium私房菜系列6 -- 深入了解Selenium RC工作原理(1)

    前一篇已经比较详细讲述了如何使用Selenium RC进行Web测试,但到底Selenium RC是什么?或者它由哪几部分组成呢?? 一.Selenium RC的组成: 关于这个问题,我拿了官网上的一 ...

  7. 测试理论-selenium的工作原理

  8. Selenium----Selenium WebDriver /RC工作原理

    1.Selenium RC 工作原理 说明:客户端库文件将命令传递给server.接着server使用selenium-core的javaScript命令传递给浏览器,浏览器会使用自带的javaScr ...

  9. selenium工作原理详解

    selenium简介 Selenium是一个用于Web应用程序自动化测试工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE(7, 8, 9, 10, 11), ...

随机推荐

  1. Storm学习笔记——简介

    1. 简介 流式计算的历史 早在7.8年前诸如UC伯克利.斯坦福等大学就开始了对流式数据处理的研究,但是由于更多的关注于金融行业的业务场景或者互联网流量监控的业务场景,以及当时互联网数据场景的限制,造 ...

  2. R语言安装openxl包报错解决办法

    在R语言中使用openxlsx包,会报错 解决办法就是: 下载安装Set-Rtool,安装时注意勾选对话框 然后在R中运行以下代码: Sys.setenv("R_ZIPCMD" = ...

  3. Scrapy shell使用

    注意:容易出现403错误,实际爬取时不会出现. response - a Response object containing the last fetched page >>>re ...

  4. Android开发 获取当前activity的屏幕截图(转载)

    首先通过下面的函数获取Bitmap格式的屏幕截图: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 pu ...

  5. 第一百五十九节,封装库--JavaScript,表单序列化结合ajax提交数据

    封装库--JavaScript,表单序列化结合ajax提交数据 封装库,表单序列化方法 /** xu_lie_biao_dan()方法,表单序列化方法,将自动获取指定表单里面的各项字段name值和va ...

  6. Hive数据类型与文件存储格式

    Hive数据类型 基础数据类型: TINYINT,SMALLINT,INT,BIGINT,BOOLEAN,FLOAT,DOUBLE,STRING,BINARY,TIMESTAMP,DECIMAL,CH ...

  7. 【python】函数参数-任意参数

    def min1(args): res=args[0] for arg in args[1:]: if arg<res: res=arg return res def min2(first,re ...

  8. phpstorm 内存设置

    https://blog.csdn.net/qq_33862644/article/details/81938970

  9. AWS系列-磁盘扩容

    1 磁盘扩容 1.1 卷介绍 aws磁盘扩容有两个方式 1.购买新的磁盘,挂载到相应的目录 2.原来磁盘做快照,购买新的磁盘,选择恢复快照到硬盘上,这样相当于,从一块硬盘上50G升级到100G 说到a ...

  10. WebSocket入门教程(五)-- WebSocket实例:简单多人聊天室

    from:https://blog.csdn.net/u010136741/article/details/51612594 [总目录]   WebSocket入门教程--大纲   [实例简介]   ...