selenium及webdriver的原理【转】
selenium与webdriver整合后,形成的新的测试工具叫做selenium2.x。在selenium1时间,selenium使用javascript来达到测试自动化的目标。
1. selenium RC
早期的Selenium使用的是Javascript注入技术与浏览器打交道,需要Selenium RC启动一个Server,将操作Web元素的API调用转化为一段段Javascript,在Selenium内核启动浏览器之后注入这段Javascript。开发过Web应用的人都知道,Javascript可以获取并调用页面的任何元素,自如的进行操作。由此才实现了Selenium的目的:自动化Web操作。这种Javascript注入技术的缺点是速度不理想,而且稳定性大大依赖于Selenium内核对API翻译成的Javascript质量高低。
2. WebDriver
当Selenium2.x 提出了WebDriver的概念之后,它提供了完全另外的一种方式与浏览器交互。那就是利用浏览器原生的API,封装成一套更加面向对象的Selenium WebDriver API,直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类的)。由于使用的是浏览器原生的API,速度大大提高,而且调用的稳定性交给了浏览器厂商本身,显然是更加科学。然而带来的一些副作用就是,不同的浏览器厂商,对Web元素的操作和呈现多少会有一些差异,这就直接导致了Selenium WebDriver要分浏览器厂商不同,而提供不同的实现。例如Firefox就有专门的FirefoxDriver,Chrome就有专门的ChromeDriver等等。(甚至包括了AndroidDriver和iOS WebDriver)
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我们希望浏览器接下来做社么事情。
在我们new一个WebDriver的过程中,Selenium首先会确认浏览器的native component是否存在可用而且版本匹配。接着就在目标浏览器里启动一整套Web Service,这套Web Service使用了Selenium自己设计定义的协议,名字叫做The WebDriver Wire Protocol。这套协议非常之强大,几乎可以操作浏览器做任何事情,包括打开、关闭、最大化、最小化、元素定位、元素点击、上传文件等等等等。
这里笔者初步画了一个图来表示各种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之后,它就能解析出需要执行的操作。截取一段源码如下:
可以看到实际发送的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的代码片段:
相信总结道这里,应该对WebDriver的运行原理应该清楚了!其实挺佩服这一套RESTful web service的设计。感觉封装WebDriver暴露出来的public API还可以更加友好跟强大一点,这次就先总结道这里,会继续分析Selenium源码,继续分享的!
3. 使用selenium2.x的经验总结
其中WebDriver的更加面向对象的方式大大降低了Selenium的入门门槛,对Web元素的操作也非常之简单易学。实际项目用起来,工作量最大的部分就是你如何解析定位到你的目标项目页面中的各种元素。好比你要定位一个Button,你可以用ID,可以用CSS,可以用XPATH,你为了点击这个Button,写了一个函数调用Selenium里的API,即WebElement里的click()或者submit(),那么另外一个Button怎么办?成百上千个Button又怎么办?
所以,你需要有一套自己实现的算法或者封装,来根据项目页面的特点提供一套通用的元素定位方式。当你的通用定位逻辑能准确的找到任何一个元素的时候,剩下的事情就顺理成章了,交给Selenium WebElement的API就可以了。这一套定位逻辑笔者觉得才是使用Selenium做Web自动化工作量最大的部分。当然有的公司Web项目使用了自己开发的UI框架,例如笔者所在的公司,这样Web元素的定位规则和算法就比较容易设计。如果Web项目开发出来的页面代码比较杂乱无章,那么你就需要更加高明和严谨的逻辑去寻找你想要操作和查看的元素了!
在笔者的项目里,笔者自己设计并封装了一套通用的API,去智能的定位页面中的各种类型的元素。比如项目里的页面有大量的dialog和wizard,都是用div+css实现的。我就提供了一个dialog组件,带有next(),save(),finish(),click(String buttonName),cancel()等方法,然后根据遮罩层和loading Icon的时间来追踪操作完成的进度。这里只是举个小小的例子,有机会再分享更多的细节
selenium及webdriver的原理【转】的更多相关文章
- 【转】selenium及webdriver的原理
主要内容转自:http://blog.csdn.net/ant_ren/article/details/7968582和http://blog.csdn.net/ant_ren/article/det ...
- selenium及webdriver的原理
主要内容转自:http://blog.csdn.net/ant_ren/article/details/7968582和http://blog.csdn.net/ant_ren/article/det ...
- Atitit WebDriver技术规范原理与概念
Atitit WebDriver技术规范原理与概念 1. Book haosyo ma1 2. WebDriver是W3C的一个标准,由Selenium主持.1 3. WebDriver如何工作 (z ...
- Selenium:WebDriver简介及元素定位
参考内容:官方API文档,下载链接:http://download.csdn.net/detail/kwgkwg001/4004500 虫师:<selenium2自动化测试实战-基于python ...
- selenium工作的大概原理
selenium的原理是什么? selenium的原理涉及到3个部分,分别是 浏览器 driver: 一般我们都会下载driver client: 也就是我们写的代码 client其实并不知道浏览器是 ...
- selenium和webdriver区别
接触selenium大概半年时间了.从开始的预研,简单的写个流程到后期的自动化框架的开发,因为本人不属于代码方面的大牛,一直的边研究边做.逐步深入学习.近期发现自己对本身selenium的发展还存在困 ...
- Selenium的webdriver的常用方法,鼠标事件
就来认识 WebDriver 中最常用的几个方法: get():跳转到的地址clear(): 清除文本. send_keys (value): 模拟按键输入. click(): 单击元素. 示例: f ...
- selenium调用webdriver异常
使用selenium调用webdriver的时候报错. from selenium import webdriver browser = webdriver.Chrome() browser.get( ...
- 第五种方式,python使用组合来添加类方法和属性(二),以selenium的webdriver为例
组合优点多,但经常比继承需要额外的代码. 上一篇是 介绍装饰器.继承.元类.mixin,四种給类动态添加类属性和方法的四种方式. 此篇介绍直接把被组合的类的属性直接加入到类里面,前面的四个例子很简单, ...
随机推荐
- Linux环境变量与文件查找
作业: 找出/etc目录下所有以.list结尾的文件 代码:locate /etc/\*.list sudo find /etc/ -name \*.list
- Sqlite数据库管理(SQLite Developer) v4.0.0.528 中文版+破解方法(申明:来源于网络)
Sqlite数据库管理(SQLite Developer) v4.0.0.528 中文破解版 SharpPlus Sqlite Developer 特性: -强大的SQL编辑器 *Sqlite Sql ...
- hdu 3016 Man Down
题意:给你n个板子,初始100生命,到达每个板子加血或者扣血,求从最上面的板子落到地面的最优解 题解:对于每一个木板,只有从左下或者从右下,所以从下往上来看,到达第n个木板的最优解为 dp[n] = ...
- Unix api
● 线程 进程的所有信息都被自己的线程共享,包括代码.全局内存.堆.栈.文件描述符. 线程拥有自己的信息,包括线程ID.一组寄存器值.栈.调度优先级和策略.信号屏蔽字.errno变量以及线程的私有数据 ...
- Jexus 安装asp.net mvc EF 项目引发的错误总
1.Linux 中的文件路径问题(配置文件路径),必须使用左斜杆 “/” 2.MVC 看 View/Web.config 下的配置文件中版本不对报错,如下: Could not locate Razo ...
- BTree和B+Tree详解
https://www.cnblogs.com/vianzhang/p/7922426.html B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引.B+树中的B代表平 ...
- Dom4j与sax 简单对比
Dom4j与sax之间的对比 dom4j不适合大文件的解析,因为它是一下子将文件加载到内存中,所以有可能出现内存溢出,sax是基于事件来对xml进行解析的,所以他可以解析大文件的xml,也正是因为如此 ...
- swift 的相机扫描
func scaning(){ //获取摄像设备 guard let device = AVCaptureDevice.default(for: .video) else { return } //输 ...
- 如何进行Django单元测试
如何进行Django单元测试 Django的单元测试使用python的unittest模块,这个模块使用基于类的方法来定义测试.类名为django.test.TestCase,继承于python的un ...
- 强制禁用gitlab的双因子认证:Two-Factor Authentication
(一)问题描述: 此博客解决如下问题:禁用gitlab的双因子认证 禁用前,如图(此时,你在gitlab中什么也干不了) (二)思路分析: 百度了很多方法,都不可靠(如不可靠的说明:https://s ...