相信很多测试小伙伴儿都听过或者使用过web自动化selenium,那您有没有研究过selenium的原理呢?为什么要使用webdriver.exe,webdriver.exe是干啥用的?selenium.common.exceptions.WebDriverException: Message: 'xxxdriver' executable needs to be in PATH如何解决的 ?今天和大家一起分析下selenium整体运行原理,有一个直观的认识。

以python为例

此处省略环境搭建和安装过程了,不知道的小伙伴儿可以自行百度。

大家都知道在使用selenium时,需要先要导入webdriver,通过webriver模块实例化driver对象

from selenium import webdriver
chrome = webdriver.Chrome()

webdriver.Chrome()都做了什么?

通过跟踪Chrome类的__init__方法发现,在初始化时调用了Service类的start方法

# WebDriver初始化方法,executable_path为chromedriver
def __init__(self, executable_path="chromedriver", port=0,
options=None, service_args=None,
desired_capabilities=None, service_log_path=None,
chrome_options=None, keep_alive=True) # Service类初始化和调用start方法
from .service import Service
self.service = Service(
executable_path,
port=port,
service_args=service_args,
log_path=service_log_path)
self.service.start()

继续跟踪Service类中start方法

cmd = [self.path]
cmd.extend(self.command_line_args())
self.process = subprocess.Popen(cmd, env=self.env,
close_fds=platform.system() != 'Windows',
stdout=self.log_file,
stderr=self.log_file,
stdin=PIPE)

cmd列表的第一个参数是传入的executable_path="chromedriver"

cmd列表的第二个参数是可用的端口号

# class Service(object)中的方法,说明该方法需要子类重写
def command_line_args(self):
raise NotImplemented("This method needs to be implemented in a sub class") # 子类class Service(service.Service)
def command_line_args(self):
return ["--port=%d" % self.port] + self.service_args # self.port 属性在子类Service未声明,说明是在父类中声明的
# 父类中的__init__方法中
self.port = port
if self.port == 0:
self.port = utils.free_port()
# 由此可知port是调用utils.free_port获取一个可用端口,这就是为什么每次运行端口都不一样的原因所在

从上面分析可以得到cmd的参数为

cmd = ['chromedriver', '--port=52857']

端口是随机可用的

即start方法实际是使用subprocess中的Popen方法执行cmd中的命令chromedriver --port=52857

我们在dos窗口中执行该命令

貌似是起了一个服务,在浏览器输入 localhost:52857试试

可以访问,那关掉该cmd窗口再进行访问呢?

无法访问了,可以看出subprocess.Popen(cmd)实际是启动了一个服务,那cmd命令中chromewebdrive是什么呢?

通过命令where chromewebdriver,发现 chromewebdriver就是我们添加到path路径的浏览器驱动

双击运行chromewebdriver.exe 发现,和subprocess.Popen(cmd)是惊人的相似,只是端口不同而已,也是可以通过浏览器访问

再执行完subprocess.Popen(cmd),紧接着执行RemoteWebDriver的初始化方法,代码如下:

# RemoteWebDriver类的初始化方法
RemoteWebDriver.__init__(
self,
command_executor=ChromeRemoteConnection(
remote_server_addr=self.service.service_url,
keep_alive=keep_alive),
desired_capabilities=desired_capabilities)

通过对代码进行跟踪,RemoteWebDriver.__init__实际就是通过http的形式向webdriverserver获取一个session

综上webdriver.Chrome()其实就是启动了一个本地服务,并通过http获取一个新的session

接下来继续分析chrome.get('http://www.baidu.com')都做什么?

def get(self, url):
"""
Loads a web page in the current browser session.
"""
self.execute(Command.GET, {'url': url}) # 都是调用的 self._request发起http请求
def execute(self, command, params):
return self._request(command_info[0], url, body=data)

通过print或者debug,get方法本质也是向webdriver server 发起一次http请求,session/${session}/url

为了验证上说结论我们用接口的形式是否可以打开chrome浏览器

步骤:

1、本地双击webdriver.exe 启动一个一个webdriver 服务,端口9515

2、通过接口localhost:9515/session, 获取session

3、通过接口localhost:9515/session/${session}/url,打开浏览器

接口1
localhost:9515/session
method:
POST
params:
{"desiredCapabilities": {"version": "", "platform": "ANY", "goog:chromeOptions": {"args": [], "extensions": []}, "browserName": "chrome"}, "capabilities": {"alwaysMatch": {"goog:chromeOptions": {"args": [], "extensions": []}, "platformName": "any", "browserName": "chrome"}, "firstMatch": [{}]}}
接口2
session/${session}/url 
method: POST
params: { "url": "http://www.baidu.com", "sessionId": "${session}" }

在jmeter中运行上述接口,启动了Chrome浏览器比打开百度首页

综上可以得出selenium的整个交互过程了,下面就是selenium的运行原理,写得不对的欢迎板砖

思考:

selenium web UI自动化能否可以向接口自动化那些来编写web UI自动化呢?这样有什么好处和不足

selenium原理解析的更多相关文章

  1. Selenium原理初步--Android自动化测试学习历程

    章节:自动化基础篇——Selenium原理初步(第五讲) 注:其实所有的东西都是应该先去用,但是工具基本都一样,底层都是用的最基础的内容实现的,测试应该做的是: (1)熟练使用工具,了解各个工具的利弊 ...

  2. APPcrawler基础原理解析及使用

    一.背景 一年前,我们一直在用monkey进行Android 的稳定性测试 ,主要目的就是为了测试app 是否会产生Crash,是否会有ANR,页面错误等问题,在monkey测试过程中,实现了脱离Ca ...

  3. [原][Docker]特性与原理解析

    Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...

  4. 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现

    本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...

  5. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  6. Web APi之过滤器创建过程原理解析【一】(十)

    前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把[筛子],那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从 ...

  7. GeoHash原理解析

    GeoHash 核心原理解析       引子 一提到索引,大家脑子里马上浮现出B树索引,因为大量的数据库(如MySQL.oracle.PostgreSQL等)都在使用B树.B树索引本质上是对索引字段 ...

  8. alibaba-dexposed 原理解析

    alibaba-dexposed 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49821413 原理参考地址: htt ...

  9. 支付宝Andfix 原理解析

    支付宝Andfix 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49802429 原理参考地址: http://blo ...

随机推荐

  1. 解决html 图片缓存问题

    <!--问题:上传一张图片,通过js更新src属性刷新图片使其即时显示时, 当img的src当前的url与上次地址无变化时(只更改图片,名称不变,不同图片名称相同)图片不变化(仍显示原来的图片) ...

  2. git 学习笔记--Feature分支

    软件开发中,总有无穷无尽的新的功能要不断添加进来. 添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合 ...

  3. P1361 小M的作物 (最大流)

    题目 P1361 小M的作物 解析 把\(A\)看做源点,把\(B\)看做汇点,先不考虑额外情况 显然,这是一种两者选其一的问题,我们选择一部分边割去,使这部分边的贡献最小,就是求最小割,我们求出了收 ...

  4. 30个关于Shell脚本的经典案例(中)

    本文目录 11.iptables自动屏蔽访问网站频繁的IP 12.判断用户输入的是否为IP地址 13.判断用户输入的是否为数字 14.给定目录找出包含关键字的文件 15.监控目录,将新创建的文件名追加 ...

  5. provide inject应用及和props对比

    之前本人写过几篇element ui源码解析,其中提到provide/inject,当时只是匆匆带过,没有做深入研究,直到后来一次开发,需要实现孙组件更改父组件的值才想起来,原来这一对属性有如此大的用 ...

  6. 使用wxpy这个基于python实现的微信工具库的一些常见问题

    使用如下的命令行安装: pip install wxpy Collecting wxpy Downloading https://files.pythonhosted.org/packages/6b/ ...

  7. 计算地图上两点间的距离PHP类

    计算地图上两点间的距离,使用的是谷歌地图 <?php class GeoHelper { /** * @param int $lat1 * @param int $lon1 * @param i ...

  8. kindedtor 数据传输问题

    <script src="/static/kindeditor/kindeditor-all.js"></script><script src=&qu ...

  9. MySQL MHA--在线主库切换(Online master switch)

    在线主库切换(Online master switch)条件 1.所有节点正常运行,无论时原主还是新主或者其他从库 if ( $#dead_servers >= 0 ) { $log->e ...

  10. BootstrapValidator 表单验证超详细教程

    一. 引入js 和css文件 在有jquery和bootstrap的页面里引入 bootstrapValidator.js bootstrapValidator.css 链接: https://pan ...