搞懂webdriver的底层原理,才敢说自己懂自动化!
Posted zgq123456
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搞懂webdriver的底层原理,才敢说自己懂自动化!相关的知识,希望对你有一定的参考价值。
搞懂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。
![技术图片](https://pics6.baidu.com/feed/3812b31bb051f81952ed76afb2ffc5e92c73e7df.jpeg?token=f5e6b0fe3a9b86237dd7925baf488cb4&s=49A43C7258605682496452E502007023)
从上图,测试代码输入操作给webdriver,webdriver再去控制浏览器,最终达到的效果就是代码实现对浏览器的操作。
三:查找元素
以查找元素为例,查看代码与webdriver的交互。以下python为例:
![技术图片](https://pics7.baidu.com/feed/b219ebc4b74543a95db7e82d775c0586b8011476.jpeg?token=eee6fb5c98ad8fb579607b604fd8a107)
这里driver是webdriver.Chrome()的对象,我们查看webdriver.Chrome()的源码。发现本质是 from .chrome.webdriver import WebDriver as Chrome
从目录名可知这来自chrome的webdriver,再次对这个WebDriver溯源,发现它是继承了一个RemoteWebDriver类。注释的含义是:控制ChromeDriver并允许驱动浏览器。
![技术图片](https://pics6.baidu.com/feed/a08b87d6277f9e2f0cb139d6737b6620b999f333.jpeg?token=f05a2ecd45c9278eaf204752d21273bd&s=8570753317F86C220C75D0CA0000C0B2)
再次对继承的RemoteWebDriver类溯源。
发现其是:selenium.webdriver.remote.webdriver.WebDriver。
![技术图片](https://pics7.baidu.com/feed/c2cec3fdfc0392450724d1d4efdf2bc67c1e2523.jpeg?token=e694dc9b7e8c66e011c3e24dc3e92e07&s=0C6470330B1B50494C7500DE0000C0B2)
注释的含义是:通过向远程服务器发送命令来控制浏览器。 该服务器应该运行WebDriver有线协议。这里先停一下,等会我们会再回来继续了解这个类。以python为例,我们在在selenium库中,通过ID获取界面元素的方法是这样的:
![技术图片](https://pics4.baidu.com/feed/4e4a20a4462309f790f9dce71b4583f7d6cad604.jpeg?token=fbd0f8d340aca814cd5f8a3c54d9ec52)
一个名为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。
![技术图片](https://pics7.baidu.com/feed/9e3df8dcd100baa19fbc08c42e5b3616c9fc2e88.jpeg?token=5300e01afb722e931add1a55637a826d&s=85707133073A55200C54A0DA0000C0B2)
这个方法有两个参数: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返回给测试代码,测试代码经过解析处理后得到想要的数据。
四:总结
![技术图片](https://pics3.baidu.com/feed/960a304e251f95ca76a2bd03a15cf03a660952fb.jpeg?token=3dedb8c9b6b70e7ea203bd6eddd44c42&s=88225D329F38440108C53DDE0200E0B2)
初学者文中难免可能有疏漏之处,希望各位大佬指正。
五:补充
为了怕同志们理解错,把大佬说的selenium工作原理写在下面。
本菜鸟是在此基础上从另一角度出发来看:
◆ Service: service->subprocess调用命令行打开webdriver.exe
◆ Client: urlib3->访问服务(接口)
以上是关于搞懂webdriver的底层原理,才敢说自己懂自动化!的主要内容,如果未能解决你的问题,请参考以下文章