TA的每日心情 | 擦汗 2022-8-30 09:02 |
---|
签到天数: 2 天 连续签到: 2 天 [LV.1]测试小兵
|
接触selenium大概半年时间了。从开始的预研,简单的写个流程到后期的自动化框架的开发,因为本人
不属于代码方面的大牛,一直的边研究边做。逐步深入学习。近期发现自己对本身selenium的发展还
存在困惑,这个也会困扰刚开始做的人,不了解为啥又是selenium、又是webdriver的。这些基本概念
随着深入的开发在不懂、了解、混沌、清晰这个过程中逐渐的展现开来。目前我的框架java+testng
+ant已经成型。但是发现自己对selenium的一些基本原理还有些混沌,所以特意停下来回头梳理一下
,查找了很多的资料,这些很多信息是从不同文章的收获到的,这里按照自己的思路进行一定的梳理
,引用一些自己看到的写的比较清晰的说明,很感谢这些前辈的分享,这里做个记录,也分享给大家。
追踪溯源,WebDriver 和 Selenium 本是两个独立的项目,实现机制也是不同的。 Selenium 2 中将两
者合并,这究竟有什么用意呢?WebDriver 比 Selenium 又有什么优势呢?我们该如何选择使用 Sele
nium 还是 WebDriver 呢?先梳理一些 WebDriver 的基本知识和使用方法。因为是Selenium 2 中将
两者合并的,通常我们把Selenium 2 称为 WebDirver,Selenium 1.x称为Selenium(Selenium1.x 时
通常指的是 Selenium RC,所以 Selenium 也指 Selenium RC)。
selenium1.x
selenium 1.0包括:selenium IDE、selenium Grid、selenium RC三部分。
selenium IDE:firefox的一个插件,可以录制和回放脚本。
selenium Grid:用于实现分布式测试。利用Grid,可以很方便地同时在多台机器上和异构环境中并行
运行多个测试事例。
selenium RC:selenium 的核心部分,可以实现利用selenium的代理服务器来实现访问浏览器实现自
动化测试。
其中:selenium RC分为:Client和Selenium Server。
client实现自动化脚本,Selenium Server负责控制浏览器行为。
Selenium Server分为3部分。
Launcher:启动浏览器
Http Proxy:selenium Server的Http代理
Core:嵌入到浏览器的js代码。
有Launcher启动浏览器,将core嵌入到浏览器,并把浏览器代理设置为selenium Server的Http Proxy。
使用的是JavaScript注入技术与浏览器打交道,需要Selenium RC启动一个Server,将操作Web元素
的API调用转化为一段段Javascript,在Selenium内核启动浏览器之后注入这段Javascript。开发过
Web应用的人都知道,Javascript可以获取并调用页面的任何元素,自如的进行操作。由此才实现
了Selenium的目的:自动化Web操作。这种Javascript注入技术的缺点是速度不理想,而且稳定性
大大依赖于Selenium内核对API翻译成的Javascript质量高低。
Selenium 2.x
Selenium 2,又名 WebDriver,它的主要新功能是集成了 Selenium 1.0 以及 WebDriver(WebDriv
er 曾经是 Selenium 的竞争对手)。也就是说 Selenium 2 是 Selenium 和 WebDriver 两个项目的合
并,即 Selenium 2 兼容 Selenium,它既支持 Selenium API 也支持 WebDriver API。
当Selenium2.x 提出了WebDriver的概念之后,它提供了完全另外的一种方式与浏览器交互。那就
是利用浏览器原生的API,封装成一套更加面向对象的Selenium WebDriver API,直接操作浏览器
页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类
的)。由于使用的是浏览器原生的API,速度大大提高,而且调用的稳定性交给了浏览器厂商本身
,显然是更加科学。然而带来的一些副作用就是,不同的浏览器厂商,对Web元素的操作和呈现
多少会有一些差异,这就直接导致了Selenium WebDriver要分浏览器厂商不同,而提供不同的实
现。例如Firefox就有专门的FirefoxDriver,Chrome就有专门的ChromeDriver等等。(包括了Andr
oidDriver和iOS WebDriver)
WebDriver与之前Selenium的JS注入实现不同,直接利用了浏览器native support来操作浏览器。
所以对于不同平台,不同的浏览器,必须依赖一个特定的浏览器的native component来实现把We
bDriver API的调用转化为浏览器的native invoke。
在我们new一个WebDriver的过程中,Selenium首先会确认浏览器的native component是否存在
可用而且版本匹配。接着就在目标浏览器里启动一整套Web Service,这套Web Service使用了Se
lenium自己设计定义的协议,名字叫做The WebDriver Wire Protocol。这套协议非常之强大,几
乎可以操作浏览器做任何事情,包括打开、关闭、最大化、最小化、元素定位、元素点击、上传
文件等等等等。
WebDriver Wire协议是通用的,也就是说不管是FirefoxDriver还是ChromeDriver,启动之后都会
在某一个端口启动基于这套协议的Web Service。例如FirefoxDriver初始化成功之后,默认会从h
ttp://localhost:7055开始,而ChromeDriver则大概是http://localhost:46350之类的。接下来,我
们调用WebDriver的任何API,都需要借助一个ComandExecutor发送一个命令,实际上是一个H
TTP request给监听端口上的Web Service。在我们的HTTP request的body中,会以WebDriver
Wire协议规定的JSON格式的字符串来告诉Selenium我们希望浏览器接下来做社么事情。
借用一张别资料中看到的图,觉得画的很好,因为很多博客中看到过,也不知道源出处原作者是
谁呢,这里表示感谢。
从上图中我们可以看出,不同浏览器的WebDriver子类,都需要依赖特定的浏览器原生组件,例
如Firefox就需要一个add-on名字叫webdriver.xpi。而IE的话就需要用到一个dll文件来转化Web Se
rvice的命令为浏览器native的调用。另外,图中还标明了WebDriver Wire协议是一套基于RESTfu
l的web service。
关于WebDriver Wire协议的细节,比如希望了解这套Web Service能够做哪些事情,可以阅读Se
lenium官方的协议文档, 在Selenium的源码中,我们可以找到一个HttpCommandExecutor这个
类,里面维护了一个Map<String, CommandInfo>,它负责将一个个代表命令的简单字符串key
,转化为相应的URL,因为REST的理念是将所有的操作视作一个个状态,每一个状态对应一个
URI。所以当我们以特定的URL发送HTTP request给这个RESTful web service之后,它就能解析出
需要执行的操作。
可以看到实际发送的URL都是相对路径,后缀多以/session/:sessionId开头,这也意味着WebDriv
er每次启动浏览器都会分配一个独立的sessionId,多线程并行的时候彼此之间不会有冲突和干扰
。例如我们最常用的一个WebDriver的API,getWebElement在这里就会转化为/session/:sessionI
d/element这个URL,然后在发出的HTTP request body内再附上具体的参数比如by ID还是CSS还
是Xpath,各自的值又是什么。收到并执行了这个操作之后,也会回复一个HTTP response。内
容也是JSON,会返回找到的WebElement的各种细节,比如text、CSS selector、tag name、class
name等等。
在 Selenium 2 中,Selenium Grid 被集成到了 Selenium Server 中,即是包含在 selenium-server-s
tandalone-x-x-x.jar 包中,好处就是更简洁更方便了!Selenium Grid 包含有两种角色,hub 和 n
ode,其中 hub 是用来接收所有的请求,并将请求分发给不同的 node;node 指的便是实际执行
测试的节点,它包含 Selenium 和 WebDriver 两种类型,其中 Selenium 是兼容 Selenium 1 中的
Selenium RC。
|
|