转载自:https://www.cnblogs.com/testermark/p/3546287.html

WebDriver的工作原理:

 在我们new一个WebDriver的过程中,Selenium首先会确认浏览器的native component是否存在可用而且版本匹配。接着就在目标浏览器里启动一整套Web Service(实际上就是浏览器厂商提供的driver, 比如IEDriver, ChromeDriver,它们都实现了WebDriver's wire protocol.),这套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我们希望浏览器接下来做什么事情。

1).  WebDriver 启动目标浏览器,并绑定到指定端口。该启动的浏览器实例,做为web driver的remote server。

2).   Client 端通过CommandExcuter 发送HTTPRequest 给remote server 的侦听端口(通信协议: the webriver wire protocol)

3).   Remote server 需要依赖原生的浏览器组件(如:IEDriver.dll,chromedriver.exe),来转化转化浏览器的native调用。

那么remote server端的这些功能是如何实现的呢?答案是浏览器实现了webdriver的统一接口,这样client就可以通过统一的restful的接口去进行浏览器的自动化操作。目前webdriver支持ie, chrome, firefox, opera等主流浏览器,其主要原因是这些浏览器实现了webdriver约定的各种接口。

可以更通俗的理解:由于客户端脚本(java, python, ruby)不能直接与浏览器通信,这时候可以把WebService当做一个翻译器,它可以把客户端代码翻译成浏览器可以识别的代码(比如js).客户端 (也就是测试脚本)创建1个session,在该session中通过http请求向WebService发送restful的请 求,WebService翻译成浏览器懂得脚本传给浏览器,浏览器把执行的结果返回给WebService,WebService把返回的结果做了一些封 装(一般都是json格式),然后返回给client,根据返回值就能判断对浏览器的操作是不是执行成功

摘自官网对于chrome driver的描述:

The ChromeDriver consists of three separate pieces. There is the browser itself ("chrome"), the language bindings provided by the Selenium project ("the driver") and an executable downloaded from the Chromium project which acts as a bridge between "chrome" and the "driver". This executable is called "chromedriver", but we'll try and refer to it as the "server" in this page to reduce confusion.

大概意思就是我们下载的chrome可执行文件(.exe)是为作为浏览器与client(language binding)桥梁的作用,也更印证了对于Web Service(driver)的理解。

举个实际的例子:

WebDriver diver = new FirefoxDriver();
driver.get("http://google.com");
 
在执行 driver.get("http://google.com");  这句代码时,client也就是我们的测试代码向Web Service(remote server)发送了如下的请求:
POST session/285b12e4-2b8a-4fe6-90e1-c35cba245956/url
post_data {"url":"http://google.com"} 
 
通过post的方式请求localhost:port/hub/session/session_id/url地址,请求浏览器完成跳转url的操作。
 
如果上述请求是可接受的,或者说Web Service是实现了这个接口,那么Web Service会跳转到该post data包含的url,并返回如下的response
{"name":"get","sessionId":"285b12e4-2b8a-4fe6-90e1-c35cba245956","status":0,"value":""}
 
该response中包含如下信息
name:Web Service端的实现的方法的名称,这里是get,表示跳转到指定url;
sessionId:当前session的id;
status:请求执行的状态码,非0表示未正确执行,这里是0,表示一切ok不必担心;
value:请求的返回值,这里返回值为空,如果client调用title接口,则该值应该是当前页面的title;
 
如果client发送的请求是定位某个特定的页面元素,则response的返回值可能是这样的:
{"name":"findElement","sessionId":"285b12e4-2b8a-4fe6-90e1-c35cba245956","status":0,"value":{"ELEMENT":"{2192893e-f260-44c4-bdf6-7aad3c919739}"}}
 
name,sessionId,status跟上面的例子是差不多的,区别是该请求的返回值是ELEMENT:{2192893e- f260-44c4-bdf6-7aad3c919739},表示定位到元素的id,通过该id,client可以发送如click之类的请求与 server端进行交互。

下图表示了各种WebDriver的工作原理

从上图中我们可以看出,不同浏览器的WebDriver子类,都需要依赖特定的浏览器原生组件,例如运行Firefox就需要一个 add-on名字叫webdriver.xpi。而IE的话就需要用到一个dll文件来转化Web Service的命令为浏览器native的调用。另外,图中还标明了WebDriver Wire协议是一套基于RESTful的web service

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

  1. 1 .put(NEW_SESSION, post("/session"))
  2. 2 .put(QUIT, delete("/session/:sessionId"))
  3. 3 .put(GET_CURRENT_WINDOW_HANDLE, get("/session/:sessionId/window_handle"))
  4. 4 .put(GET_WINDOW_HANDLES, get("/session/:sessionId/window_handles"))
  5. 5 .put(GET, post("/session/:sessionId/url"))
  6. 6
  7. 7 // The Alert API is still experimental and should not be used.
  8. 8 .put(GET_ALERT, get("/session/:sessionId/alert"))
  9. 9 .put(DISMISS_ALERT, post("/session/:sessionId/dismiss_alert"))
  10. 10 .put(ACCEPT_ALERT, post("/session/:sessionId/accept_alert"))
  11. 11 .put(GET_ALERT_TEXT, get("/session/:sessionId/alert_text"))
  12. 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. 1 try {
  2. 2 response = new JsonToBeanConverter().convert(Response.class, responseAsText);
  3. 3 } catch (ClassCastException e) {
  4. 4 if (responseAsText != null && "".equals(responseAsText)) {
  5. 5 // The remote server has died, but has already set some headers.
  6. 6 // Normally this occurs when the final window of the firefox driver
  7. 7 // is closed on OS X. Return null, as the return value _should_ be
  8. 8 // being ignored. This is not an elegant solution.
  9. 9 return null;
  10. 10 }
  11. 11 throw new WebDriverException("Cannot convert text to response: " + responseAsText, e);
  12. 12 } //...

PS:如果想更深入的了解WebDriver的架构,可以参考该文章http://www.aosabook.org/en/selenium.html

[转载]WebDriver工作原理的更多相关文章

  1. [转载] zookeeper工作原理、安装配置、工具命令简介

    转载自http://www.cnblogs.com/kunpengit/p/4045334.html 1 Zookeeper简介Zookeeper 是分布式服务框架,主要是用来解决分布式应用中经常遇到 ...

  2. [转载] MapReduce工作原理讲解

    转载自http://www.aboutyun.com/thread-6723-1-1.html 有时候我们在用,但是却不知道为什么.就像苹果砸到我们头上,这或许已经是很自然的事情了,但是牛顿却发现了地 ...

  3. WebDriver工作原理

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

  4. Selenium WebDriver 工作原理

    WebDriver与之前Selenium的js注入实现不同:Selenium通过JS来定位元素处理元素(基本上所有元素都可以定位到)WebDriver通过WebDriver API定位处理元素:通过浏 ...

  5. [转载]Appium工作原理

    [Appium]Appium工作原理 2017-09-13 15:28 sophia194910 阅读(7658) 评论(0) 编辑 收藏 参考:http://www.cnblogs.com/zhjs ...

  6. 转载: keepalived工作原理和配置说明

    转自:http://outofmemory.cn/wiki/keepalived-configuration keepalived是什么 keepalived是集群管理中保证集群高可用的一个服务软件, ...

  7. (转载)HashMap工作原理

    HashMap是近些年来java面试中常问到的知识点,很多人(包括我在内)都知道HashMap的用法,也知道HashMap与HashTable之间的区别,但是却不知其所以然,于是乎,本人开始查阅相关资 ...

  8. [转载] Lucene 工作原理

    转载自http://www.cnblogs.com/dewin/archive/2009/11/24/1609905.html Lucene是一个高性能的java全文检索工具包,它使用的是倒排文件索引 ...

  9. WebDriver 工作原理

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

随机推荐

  1. 武汉邀请赛 Key Logger 双向链表

    Key Logger Time Limit: 3000ms Case Time Limit: 3000ms Memory Limit: 65536KB   64-bit integer IO form ...

  2. UOJ#54 BZOJ3434 [WC2014]时空穿梭

    题目描述 小 X 驾驶着他的飞船准备穿梭过一个 \(n\) 维空间,这个空间里每个点的坐标可以用 \(n\) 个实数表示,即 \((x_1,x_2,\dots,x_n)\). 为了穿过这个空间,小 X ...

  3. bootstrap 中的 iCheck 全选反选功能的实现

    喜欢bootstrap 风格的同学应该知道,iCheck的样式还是很好看的. 官网: http://www.bootcss.com/p/icheck/ 进入正题,iCheck提供了一些方法,可以进行全 ...

  4. jQuery 滚动条滚动

    1.将div的滚动条滚动到最底端 <div class="container"></div> var $container=$(".contain ...

  5. 远景WEBGIS平台实现客户端SHP文件加载

    远景WEBGIS平台的研发目前取得新进展,实现客户端shp文件的加载,可以不经过PC上的数据转换工具转换. 远景WEBGIS平台(RemoteGIS)是基于HTML5自主研发的新一代WEBGIS基础平 ...

  6. 利用Mongodb做地理空间查询

    MongoDB 是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. 前言 在移动开发中,经常会用到定位的功能,例如美团.饿了么.猫眼电影等的app ...

  7. Forword与sendRedirect的区别

    二.本质区别 解释一 一句话,转发是服务器行为,重定向是客户端行为.为什么这样说呢,这就要看两个动作的工作流程: 转发过程:客户浏览器发送http请求——>web服务器接受此请求——>调用 ...

  8. dbcp2、c3p0、druid连接池的简单配置

    引入Maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...

  9. AndroidUI多线程网络请求更新导致BUG

    昨天发现一个问题,以前做好的UI列表不用正常显示了,必须,下拉一下,才能加载内容,以前是页面自动加载第一屏幕的. 这个就不好了,只是给页面加了一个按钮啊,不应该造成这么大的问题. 按钮就是设置了一个位 ...

  10. 详细故障排除步骤:针对 Azure 中到 Windows VM 的远程桌面连接问题

    本文提供详细的故障排除步骤,用于为基于 Windows 的 Azure 虚拟机诊断和修复复杂的远程桌面错误. Important 若要消除更常见的远程桌面错误,请务必先阅读远程桌面的基本故障排除文章, ...