搞懂webdriver的底层原理,才敢说自己懂自动化!

一:Selenium的历史

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要分浏览器厂商不同,而提供不同的实现。

二:结构

以下进入正题,要通过selenium实现自动化测试,最最主要是需要三种东西:测试需要用的代码、webdriver、浏览器。今天想要分享的也是这三者关系。

① 代码

selenium支持多种语言(java/c#/python/ruby)。测试工程师通过编程语言,调用浏览器对应API实现需要的功能。

② webdriver

webdriver,就像是一个媒介。代码驱动webdriver。上文提过,不同浏览器有不同的webdriver。例如火狐的FirefoxDriver,谷歌的 ChromeDriver。

③ 浏览器

不同的浏览器对应不同的webdriver。

从上图,测试代码输入操作给webdriver,webdriver再去控制浏览器,最终达到的效果就是代码实现对浏览器的操作。

三:查找元素

以查找元素为例,查看代码与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返回给测试代码,测试代码经过解析处理后得到想要的数据。

四:总结

初学者文中难免可能有疏漏之处,希望各位大佬指正。

五:补充

为了怕同志们理解错,把大佬说的selenium工作原理写在下面。

本菜鸟是在此基础上从另一角度出发来看:

◆ Service: service->subprocess调用命令行打开webdriver.exe

◆ Client: urlib3->访问服务(接口)

原文地址:https://www.cnblogs.com/zgq123456/p/11548528.html

时间: 2024-10-18 05:37:08

搞懂webdriver的底层原理,才敢说自己懂自动化!的相关文章

一步搞清楚多态与类初始化的底层原理

首先我们先看一个段非常有代表性的代码,里面一口气牵扯到了多态和类初始化顺序知识. public class Test { public static void main(String[] args) { A test = new B(); } } class A { int value = 10; A() { System.out.println("父类构造器"); process(); } public void process() { System.out.println(&quo

计算机底层原理杂谈(白话文)

简单说一下写这篇文章的缘由.首先这个不是教学类型的,是我Java实在学不下去了,因为好多计算机底层原理都不是很清楚,每次学新东西都由于想不明白底层原理困惑,所以下决心停止学习Java的新东西,开始搞明白底层.一开始搞的所谓的底层是“Java虚拟机”,然后又C语言汇编语言什么的,其实是想图快,尽快接近现在做的事情.后来发现不行,这事快不了,所以干脆就从物理层面用导线灯泡集成芯片开始动手做一个cpu开始吧.其实也没多久,大概三个多月吧,从我之前写的[从零开始自制cpu]系列的学习文章也可以看到开始时

面试官再问你 HashMap 底层原理,就把这篇文章甩给他看

前言 HashMap 源码和底层原理在现在面试中是必问的.因此,我们非常有必要搞清楚它的底层实现和思想,才能在面试中对答如流,跟面试官大战三百回合.文章较长,介绍了很多原理性的问题,希望对你有所帮助~ 目录 本篇文章主要包括以下内容: HashMap 的存储结构 常用变量说明,如加载因子等 HashMap 的四个构造函数 tableSizeFor()方法及作用 put()方法详解 hash()方法,以及避免哈希碰撞的原理 resize()扩容机制及原理 get()方法 为什么HashMap链表会

MVC底层原理

窥探ASP.Net MVC底层原理 实现跨越Session的分布式TempData 1.问题的引出 我相信大家在项目中都使用过TempData,TempData是一个字典集合,一般用于两个请求之间临时缓存数据或者页面之间传递消息.也都知道TempData是用Session来实现的,既然是用Session来实现的,那么模式就是线程模式,这样的Session是没法用到分布式系统中的,那么在多台机器上部署,怎么做到Session在多台机器中共存,这就涉及到分布式存储.那该如何实现TempData的分布

NGUI所见即所得之深入剖析UIPanel,UIWidget,UIDrawCall底层原理

NGUI所见即所得之深入剖析UIPanel,UIWidget,UIDrawCall底层原理 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 之前项目中用的NGUI的版本是3.0.7 f3,开始的时候感觉没有什么问题,直达最近项目UI的完成度比较高时,就突然出现掉帧很严重的现象,即使只有一个UI打开(其他都是active = false的情况下),打开profier,发现UIPanel LateUpdate 竟然占了CPU使用率的50%左右

Javascript属性constructor/prototype的底层原理

在Javascript语言中,constructor属性是专门为function而设计的,它存在于每一个function的prototype属性中.这个constructor保存了指向function的一个引用.在定义一个函数(代码如下所示)时, function F() { // some code } JavaScript内部会执行如下几个动作: 为该函数添加一个原形属性(即prototype对象). 为prototype对象额外添加一个constructor属性,并且该属性保存指向函数F的

并发编程艺术-锁类型以及底层原理

Java并发编程艺术-并发机制的底层原理实现 1.Volatile 定义: Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量. volatile借助Java内存模型保证所有线程能够看到最新的值.(内存可见性) 实现原理: 将带有volatile变量操作的Java代码转换成汇编代码后,可以看到多了个lock前缀指令(X86平台CPU指令).这个lock指令是关键,在多核处理器下实现两个重要操作: 1.将当前处理器缓存行的数据写回到系

Java多态的底层原理

作为一门面向对象语言,Java 拥有封装.继承.多态三大特性.多态就是允许不同类的对象对同一消息做出响应.基于多态,可以消除一些类型耦合关系,实现可替换.可扩充.Java 中使用多态特性的方法主要有,实现一个接口,实现抽象类的一个方法,覆盖父类的一个方法. Java多态的底层原理 多态的底层实现是动态绑定,即在运行时才把方法调用与方法实现关联起来.动态绑定涉及很多 JVM 的细节,全部写清楚需要很大篇幅,因此本文仅简单描述,后续会有其他文章就其中的细节一一分享. 静态绑定与动态绑定 JVM 的方

Spring Cloud底层原理

目录 一.业务场景介绍 二.Spring Cloud核心组件:Eureka 三.Spring Cloud核心组件:Feign 四.Spring Cloud核心组件:Ribbon 五.Spring Cloud核心组件:Hystrix 六.Spring Cloud核心组件:Zuul 七.总结 概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留在对Spring Cloud功能使用的层面,其底层的很多原理,很多人可能并不知晓.因此本文