转载自: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 .put(NEW_SESSION, post("/session"))
2 .put(QUIT, delete("/session/:sessionId"))
3 .put(GET_CURRENT_WINDOW_HANDLE, get("/session/:sessionId/window_handle"))
4 .put(GET_WINDOW_HANDLES, get("/session/:sessionId/window_handles"))
5 .put(GET, post("/session/:sessionId/url"))
6
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 } //...

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. JavaScript高级编程———数据存储(cookie、WebStorage)

    JavaScript高级编程———数据存储(cookie.WebStorage) <script> /*Cookie 读写删 CookieUtil.get()方法根据cookie的名称获取 ...

  2. BZOJ1927: [Sdoi2010]星际竞速(最小费用最大流 最小路径覆盖)

    题意 题目链接 Sol 看完题不难想到最小路径覆盖,但是带权的咋做啊?qwqqq 首先冷静思考一下:最小路径覆盖 = \(n - \text{二分图最大匹配数}\) 为什么呢?首先最坏情况下是用\(n ...

  3. 神奇的AC

  4. 理解position:relative

    前言:position有5个属性:static.absolute.relative.fixed和inherit.本篇博客主要介绍relative属性,因为似乎很多人对这个属性的理解很模糊,而且不清楚r ...

  5. 使用nodeJs安装Vue-cli (win10 使用管理员身份)

    TIP:win10下安装,使用管理员身份进行,否则会有权限限制. 1,安装完成node,node有自带的npm,可以直接在cmd中,找到nodeJs安装的路径下,进行命令行全局安装vue-cli.(n ...

  6. 关于 Blog 修改

    关于 Blog 修改 本 Blog 使用的是 WordPress,每次升级 WordPress 都需要修改文件,以修正一些问题,因此做个总记录,便于自己修改. 解决 WordPress 无法打开中文链 ...

  7. Mycat中间件

    数据库中间件Mycat自我介绍 一.mycat概述 1.功能介绍 mycat一个开源的分布式数据库系统,是一个实现了mysql协议的server前端用户可以把它看成一个数据库代理,用mysql客户端工 ...

  8. 【Oracle】锁表处理 SQL 错误: ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效

    问题描述有时候ORACLE数据的某些表由于频繁操作,而且比较大,会导致锁表(死锁). 问题分析(1)锁的分析ORACLE里锁有以下几种模式:0:none1:null 空2:Row-S 行共享(RS): ...

  9. Frequently Used Algo

    1. 链表 链表逆转 class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* prev = NULL; w ...

  10. DB2问题记录本

    1.System.Data.OleDb.OleDbException (0x80004005): 未指定的错误. 场景:部署网站到IIS上,使用oledb连接DB2数据库报错,开发环境正常 解决方案: ...