做了一段时间的web测试,用的是selenium2 webdriver,现在介绍一下webdriver的工作原理。

早期的Selenium使用的是Javascript注入技术与浏览器打交道,需要Selenium RC启动一个Server,将操作Web元素的API调用转化为一段段Javascript,在Selenium内核启动浏览器之后注入这段Javascript。这种Javascript注入技术的缺点是速度不理想,而且稳定性大大依赖于Selenium内核对API翻译成的Javascript质量高低。

WebDriver与之前Selenium 1的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协议是通用的,浏览器通过实现webdriver wire协议的统一接口来支持webdriver,目前已经有ie, chrome, firefox, opera等主流浏览器支持webdriver接口操作。不管是FirefoxDriver还是ChromeDriver,启动之后都会在某一个端口启动基于这套协议的Web Service。例如FirefoxDriver初始化成功之后,默认会从http://localhost:7055开始,而ChromeDriver 则大概是http://localhost:46350之类的。接下来,我们调用WebDriver的任何API,都需要借助一个ComandExecutor发送一个命令,实际上是一个HTTP request给46350端口上的Web Service。在我们的HTTP request的body中,会以WebDriver Wire协议规定的JSON格式的字符串来告诉Selenium我们希望浏览器接下来做什么事情。

不同浏览器的WebDriver子类,还需要依赖特定的浏览器原生组件,例如Firefox就需要一个add-on名字叫webdriver.xpi。而IE的话就需要用到一个dll文件来转化Web Service的命令为浏览器native的调用。

  • 当测试脚本启动firefox的时候,selenium-webdriver 会首先在新线程中启动firefox浏览器。如果测试脚本指定了firefox的profile,那么就以该profile启动,否则的话就新启1个profile,并启动firefox;

  • firefox一般是以-no-remote的方法启动,启动后selenium-webdriver会将firefox绑定到特定的端口,绑定完成后该firefox实例便作为webdriver的remote server存在;

  • 客户端(也就是测试脚本)创建1个session,在该session中通过http请求向remote server发送restful的请求,remote server解析请求,完成相应操作并返回response;

  • 客户端接受response,并分析其返回值以决定是转到第3步还是结束脚本;

webdriver是按照server – client的经典设计模式设计的。

server端就是remote server,可以是任意的浏览器。当我们的脚本启动浏览器后,该浏览器就是remote server,它的职责就是等待client发送请求并做出相应;

client端简单说来就是我们的测试代码,我们测试代码中的一些行为,比如打开浏览器,转跳到特定的url等操作是以http请求的方式发送给被 测试浏览器,也就是remote server;remote server接受请求,并执行相应操作,并在response中返回执行状态、返回值等信息;

举个实际的例子,下面代码的作用是命令firefox转跳到baidu主页:

driver = Selenium::WebDriver.for :firefoxdriver.navigate.to "http://www.baidu.com"

在执行driver.navigate.to “http://www.baidu.com” 这句代码时,client,也就是我们的测试代码向remote   server发送了如下的请求:

POST session/285b12e4-2b8a-4fe6-90e1-c35cba245956/urlpost_data {"url":"http://www.baidu.com"} 

通过post的方式请求localhost:port/hub/session/session_id/url地址,请求浏览器完成跳转url的操作。

如果上述请求是可接受的,或者说remote server实现了这个接口,那么remote server会跳转到该post data包含的url,并返回如下的response:

{"name":"get","sessionId":"285b12e4-2b8a-4fe6-90e1-c35cba245956","status":0,"value":""}

该response中包含如下信息

  • name:remote server端的实现的方法的名称,这里是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已经是W3C的一个标准,由Selenium主持。

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

nameToUrl = ImmutableMap.<String, CommandInfo>builder()          .put(NEW_SESSION, post("/session"))          .put(QUIT, delete("/session/:sessionId"))          .put(GET_CURRENT_WINDOW_HANDLE, get("/session/:sessionId/window_handle"))          .put(GET_WINDOW_HANDLES, get("/session/:sessionId/window_handles"))          .put(GET, post("/session/:sessionId/url"))            // The Alert API is still experimental and should not be used.          .put(GET_ALERT, get("/session/:sessionId/alert"))          .put(DISMISS_ALERT, post("/session/:sessionId/dismiss_alert"))          .put(ACCEPT_ALERT, post("/session/:sessionId/accept_alert"))          .put(GET_ALERT_TEXT, get("/session/:sessionId/alert_text"))          .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等等。

转载于:https://blog.51cto.com/ponyjia/1811695

Selenium webdriver实现原理相关推荐

  1. selenium原理python_通过python Selenium 库源代码来看Selenium Webdriver 实现原理

    作为一名使用Selenium开发UI自动化多年的工程师,一直都对Selenium Webdriver的实现原理感觉不是很清楚.怎么就通过脚本控制浏览器进行各种操作了呢?相信很多Selenium的使用者 ...

  2. Selenium Webdriver原理终于搞清楚了

    目录 1. Selenium的历史 2. WebDriver协议 3. Selenium驱动浏览器原理 4. 测试代码与Webdriver的交互 5. Webdriver与浏览器的关系 6. Sele ...

  3. selenium webdriver 原理概述

    背景 虽然掌握selenium webdriver提供的各种方法,就可以做web的UI自动化,但是本着知其然,也要知其所以然的态度,也为了提升自己.了解下selenium webdriver的原理是必 ...

  4. python webdriver点击指令_测开系列Selenium Webdriver Python(20)--Webdriver运行原理

    Webdriver运行原理 转帖请注明出处!谢谢 在开发Webdriver的自动化脚本过程中,Webdriver后台在创建WebDriver实例的过程中,先确认浏览器的原生组件中是否存在可匹配的版本. ...

  5. 乙醇的selenium java_揭秘webdriver实现原理 | 乙醇的开源自动化工具研究Blog

    通过研究selenium-webdriver的源码,笔者发现其实webdriver的实现原理并不高深莫测无法揣度.在这里以webdriver ruby binding的firefox-webdrive ...

  6. 【自动化测试爬虫系列】Selenium Webdriver 介绍

    一. Selenium Webdriver技术介绍 1. 简介 selenium Webdriver是一套针对不同浏览器而开发的web应用自动化测试代码库.使用这套库可以进行页面的交互操作,并且可以重 ...

  7. Selenium WebDriver的TestNG注释完整指南

    TestNG是CédricBeust创建的测试框架 ,有助于满足我们的许多测试需求. 它被广泛用于硒中. 想知道NG代表什么? 好吧,它指的是"下一代" . TestNG与Juni ...

  8. Selenium WebDriver架构

    什么是Selenium? (What is Selenium?) Selenium is an Opensource Automation testing tool which is only mea ...

  9. selenium webdriver (python)的基本用法一

    阅在线 AIP 文档: http://selenium.googlecode.com/git/docs/api/py/index.html 目录 一.selenium+python 环境搭建..... ...

  10. selenium webdriver使用

    selenium使用 引言 1.selenium课程概要 2.selenium的介绍 2.1selenium工作原理 2.2selenium模块与driver的安装 2.2.1 在python虚拟机环 ...

最新文章

  1. python的最大绘图速度_Python数据可视化之高速绘图神器PyQtGraph库,强烈建议收藏...
  2. caffe修改hdf5的datalayer
  3. MATLAB-矩阵相关计算(2)
  4. java图片预览上传_Java实现图片上传预览 (使用ajax提交)
  5. DDD理论学习系列(11)-- 工厂
  6. zookeeper下载地址及常见配置项
  7. 边缘计算架构_边缘计算与开放基础架构的重要性
  8. STM32单片机开发之让蜂鸣器发声
  9. 闲话: 恭喜园子里的MVP一下, 同时问所有奋斗在技术领域的兄弟过节好~
  10. hibernate_使用c3p0连接池配置
  11. idea卸载不干净怎么办_卸载删除面具(Magisk)后,手机不开机怎么办
  12. http://www.boobooke.com/bbs/thread-10284-1-1.html
  13. VMware虚拟机安装使用及系统安装教程
  14. 显著性检测(一)Saliency Detection: A Spectral Residual Approach
  15. SAP ABAP 输出设备设置 LP01
  16. EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE
  17. 幼麟棋牌技术分享系列:H5棋牌游戏加载速度优化
  18. 牵丝戏计算机谱,急求牵丝戏计算器谱完整版!!!
  19. vue2实现传送门效果
  20. 论文阅读--利用完全卷积和空间变换网络从部分二维观测中产生三维超声

热门文章

  1. Atitit  hre框架v5 新特性  HREv5
  2. atitit.查看预编译sql问号 本质and原理and查看原生sql语句
  3. paip.抓取网页内容--java php python
  4. paip. erlang语法C++语法对比attilax总结
  5. Rust : 简单模拟交易所与参与机构
  6. Rust : Attribute 属性 作者:Mike Tang
  7. UBS缘何突然抛弃智能投顾?全球财富管理霸主的数字化转型启示(上)
  8. (转)高盛:老牌投行新生意,华尔街“谷歌”如何炼成?
  9. 计算的未来30年:2050大会分享实录
  10. 这可能是程序员写的最暖的一首歌了