搞懂webdriver的底层原理,才敢说自己懂自动化!
Selenium的历史1
selenium1.x:这个时候的selenium,使用的是JavaScript注入技术与浏览器打交道。
需要Selenium RC启动一个Server,将操作Web元素的API调用转化为一段段Javascript,在Selenium内核启动浏览器之后注入这段Javascript。
Javascript可以获取并调用DOM的任何元素,自如的进行操作。
由此才实现了Selenium的目的:自动化Web操作。
这种Javascript注入技术的缺点是速度不理想,而且稳定性大大依赖于Selenium内核对API翻译成的Javascript质量高低。
selenium2.x:相比于selenium1.x,2.x版本整合了webdriver以及原版selenium。
两个项目合二为一,虽然名字还叫selenium,但也可以叫Webdriver。
这个版本的selenium是利用浏览器原生的API,封装成一套更加面向对象的Selenium WebDriver API。
直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类的)。
由于使用的是浏览器原生的API,速度大大提高,而且调用的稳定性交给了浏览器厂商本身,显然是更加科学。
然而带来的一些副作用就是,不同的浏览器厂商,对Web元素的操作和呈现多少会有一些差异,这就直接导致了Selenium WebDriver要分浏览器厂商不同,而提供不同的实现。
结构2
以下进入正题
要通过selenium实现自动化测试,最最主要是需要三种东西:测试需要用的代码、webdriver、浏览器
今天想要分享的也是这三者关系。
① 代码
selenium支持多种语言
(java/c#/python/ruby)。
测试工程师通过编程语言,调用浏览器对应API实现需要的功能。
② webdriver
webdriver,就像是一个媒介。
代码驱动webdriver。
上文提过,不同浏览器有不同的webdriver。
例如火狐的FirefoxDriver。
谷歌的 ChromeDriver。
③ 浏览器
不同的浏览器对应不同的webdriver。
从上图,测试代码输入操作给webdriver,webdriver再去控制浏览器,最终达到的效果就是代码实现对浏览器的操作。
查找元素3
以查找元素为例,查看代码与webdriver的交互。
以下python为例:
这里driver是webdriver.Chrome()的对象,我们查看webdriver.Chrome()的源码。
发现本质是 from .chrome.webdriver import WebDriver as Chrome
从目录名可知这来自chrome的webdriver,再次对这个WebDriver溯源,发现它是继承了一个RemoteWebDriver类。
注释的含义是:控制ChromeDriver并允许驱动浏览器。
再次对继承的RemoteWebDriver类溯源。
发现其是:
selenium.webdriver.remote.webdriver.WebDriver。
注释的含义是:通过向远程服务器发送命令来控制浏览器。
该服务器应该运行WebDriver有线协议。
这里先停一下,等会我们会再回来继续了解这个类。
以python为例,我们在在selenium库中,通过ID获取界面元素的方法是这样的:
一个名为command_executor的对象执行了execute方法。
名为command_executor的对象是RemoteConnection类的对象。
并且这个对象是在新建
selenium.webdriver.remote.webdriver.WebDriver类对象的时候就完成赋值的self.command_executor = RemoteConnection(command_executor, keep_alive=keep_alive)。
结合
selenium.webdriver.remote.webdriver.WebDriver类的类注释来看:
WebDriver类的功能是通过给一个remote server发送指令来控制浏览器。
而这个remote server是一个运行WebDriver wire protocol的server。
而RemoteConnection类就是负责与Remote WebDriver server的连接的类。
可以注意到有这么一个新建WebDriver类的对象时候的参数command_executor。
默认值等于
'http://127.0.0.1:4444/wd/hubremote'。
这个值表示的是访问server的URL。
因此这个值作为了RemoteConnection类的构造方法的参数。
因为要连接remote server,URL是必须的。
现在再来看RemoteConnection类的实例方法execute。
这个方法有两个参数:command、params。
command表示期望执行的指令的名字。
打开self._commands这个dict。
查看Command.FIND_ELEMENT的value.。
指令的URL部分包含了几个组成部分:
◆HTTP请求方法。WebDriver wire protocol中定义的指令是符合RESTful规范的,通过不同请求方法对应不同的指令操作。
◆sessionId. sessionId表示了remote server和浏览器的一个会话,指令通过这个会话变成对于浏览器的一个操作。
◆ element 这一部分用来表示具体的指令。
selenium.webdriver.remote.command.Command类里的常量指令又在各个具体的类似find_elements的实例方法中作为execute方法的参数来使用。
这样就实现了
selenium.webdriver.remote.webdriver.WebDriver类中实现各种操作的实例方法与WebDriver wire protocol中定义的指令的一一对应。
selenium.webdriver.remote.webelement.WebElement中各种在WebElement上的操作也是用类似的原理实现的。
实例方法execute的另一个参数params则是用来保存指令的参数的,这个参数将转化为JSON格式,作为HTTP请求的body发送到remote server。
remote server在执行完对浏览器的操作后得到的数据将作为HTTP Response的body返回给测试代码,测试代码经过解析处理后得到想要的数据。
总结
初学者文中难免可能有疏漏之处,希望各位大佬指正。
补充5
为了怕同志们理解错,把雨泽大佬上课说的selenium工作原理写在下面。
本菜鸟是在此基础上从另一角度出发来看:
◆ Service: service->subprocess调用命令行打开webdriver.exe
◆ Client: urlib3->访问服务(接口)
来源:
https://mp.weixin.qq.com/s/8bQe5HdqZWy-OuMc4yBI7Q
搞懂webdriver的底层原理,才敢说自己懂自动化!的更多相关文章
- Linux从头学13:想彻底搞懂“系统调用”的底层原理?建议您别错过这篇【调用门】
作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...
- 【底层原理】高级开发必须懂的"字节对齐"
认识字节对齐之前,假定int(4Byte),char(1Byte),short(2Byte) 认识字节对齐 先看段代码: struct Data1 { char a; int b; short c; ...
- mysql join 底层原理
你知道 Sql 中 left join 的底层原理吗? 2019-09-10阅读 7130 https://cloud.tencent.com/developer/column/2367 01.前 ...
- 源码解读:webdriver client的原理
前言 又到年底了,群里很多朋友说要开始备战2020金三银四,其实,我建议是,如果你不是技术大牛,就不要去凑热闹. 其实,现在(11,12月份)就是最佳换工作的时候,因为很多人想等着拿了年终再走,虽然招 ...
- 面试官再问你 HashMap 底层原理,就把这篇文章甩给他看
前言 HashMap 源码和底层原理在现在面试中是必问的.因此,我们非常有必要搞清楚它的底层实现和思想,才能在面试中对答如流,跟面试官大战三百回合.文章较长,介绍了很多原理性的问题,希望对你有所帮助~ ...
- 操作系统底层原理与Python中socket解读
目录 操作系统底层原理 网络通信原理 网络基础架构 局域网与交换机/网络常见术语 OSI七层协议 TCP/IP五层模型讲解 Python中Socket模块解读 TCP协议和UDP协议 操作系统底层原理 ...
- Android进程永生技术终极揭秘:进程被杀底层原理、APP应对技巧
1.引言 上个月在知乎上发表的由“袁辉辉”分享的关于TIM进程永生方面的文章(即时通讯网重新整理后的标题是:<史上最强Android保活思路:深入剖析腾讯TIM的进程永生技术>),短时间内 ...
- Java8线程池ThreadPoolExecutor底层原理及其源码解析
小侃一下 日常开发中, 或许不会直接new线程或线程池, 但这些线程相关的基础或思想是非常重要的, 参考林迪效应; 就算没有直接用到, 可能间接也用到了类似的思想或原理, 例如tomcat, jett ...
- 架构师之路-https底层原理
引子 先说说我对架构师的理解.从业务能力上,需要的是发现问题和解决问题的能力:从团队建设上,需要的是能培养团队的业务能力:从项目管理上,把控好整个项目和软件产品的全生命周期. 我搜索了一下架构师的培训 ...
随机推荐
- HURST 1116:选美大赛(LIS+路径输出)
选美大赛 Time Limit: 1000 MS Memory Limit: 65536 K Total Submit: 1099(318 users) Total Accepted: 349(252 ...
- java-this和super的区别
1.this和super都代表什么: - this:代表当前对象的引用,谁来调用我,我就代表谁 - super:代表当前对象父类的引用 - super(...)或者this(...)必须放在构造方法的 ...
- Python开发指南规范
分号 不要在行尾加分号, 也不要用分号将两条命令放在同一行. 行长度 每行不超过80个字符 例外: 长的导入模块语句 注释里的URL 不要使用反斜杠连接行. Python会将 圆括号, 中括号和花括号 ...
- 斐波那契数列的生成 %1e8 后的结果
方法一 用数组开,一般开到1e7,1e8 左右的数组就是极限了 对时间也是挑战 #include<bits/stdc++.h> using namespace std; ; int ...
- hibernate中带查询条件的分页
所谓分页,从数据库中分,则是封装一个分页类.利用分页对象进行分页. 但,分页往往带查询条件. 分页类的三个重要数据:[当前页码数],[数据库中的总记录数],[每页显示的数据的条数] 原理:select ...
- Percona XtraDB Cluster高可用与状态快照传输(PXC 5.7 )
Percona XtraDB Cluster(下称PXC)高可用集群支持任意节点在运行期间的重启,升级或者意外宕机,即它解决了单点故障问题.那在这个意外宕机或者重启期间,该节点丢失的数据如何再次进行同 ...
- webpack 打包产生的文件名中,hash、chunkhash、contenthash 的区别
table th:first-of-type { width: 90px; } hash 类型 区别 hash 每一次打包都会生成一个唯一的 hash chunkhash 根据每个 chunk 的内容 ...
- @RequestMapping、@Responsebody、@RequestBody和@PathVariable详解(转)
一.预备知识:@RequestMapping RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上.用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径. @Requ ...
- xshell 5中文破解版下载
xshell 5破解版是一款功能强大的终端模拟软件,支持Telnet.Rlogin.SSH.SFTP.Serial等远程协议,让用户能通过互联网直接连接远程主机.用户通过xshell 5破解版能轻松和 ...
- Hadoop YARN上运行MapReduce程序
(1)配置集群 (a)配置hadoop-2.7.2/etc/hadoop/yarn-env.sh 配置一下JAVA_HOME export JAVA_HOME=/home/hadoop/bigdata ...