当前位置: 首页 > news >正文

selenium/webdriver运行原理与机制

最近在看一些底层的东西。driver翻译过来是驱动,司机的意思。如果将webdriver比做成司机,竟然非常恰当。

我们可以把WebDriver驱动浏览器类比成出租车司机开出租车。在开出租车时有三个角色:

· 乘客:他/她告诉出租车司机去哪里,大概怎么走。

· 出租车司机:他按照乘客的要求来操控出租车。

· 出租车:出租车按照司机的操控完成真正的行驶,把乘客送到目的地。

在WebDriver中也有类似的三个角色:

· 自动化测试代码:自动化测试代码发送请求给浏览器的驱动(比如火狐驱动、谷歌驱动)。

· 浏览器的驱动:它来解析这些自动化测试的代码,解析后把它们发送给浏览器。

· 浏览器:执行浏览器驱动发来的指令,并最终完成工程师想要的操作。

所以在这个类比中:

· 工程师写的自动化测试代码就相当于是乘客。

· 浏览器的驱动就相当于是出租车司机。

· 浏览器就相当于是出租车。

下面再从技术上解释下WebDriver的工作原理:

从技术上讲,也同样是上面的三个角色:

· WebDriver API(基于Java、Python、C#等语言)。

· 对于java语言来说,就是下载下来的selenium的Jar包,比如selenium-java-3.8.1.zip包,代表Selenium3.8.1的版本。

· 浏览器的驱动(browser driver),每个浏览器都有自己的驱动,均以exe文件形式存在。比如谷歌的chromedriver.exe、火狐的geckodriver.exe、IE的IEDriverServer.exe浏览器。

浏览器当然就是我们很熟悉的常用的各种浏览器。那在WebDriver脚本运行的时候,它们之间是如何通信的呢?为什么同一个browser driver即可以处理java语言的脚本,也可以处理python语言的脚本呢?让我们来看一下,一条Selenium脚本执行时后端都发生了哪些事情:

· 对于每一条Selenium脚本,一个http请求会被创建并且发送给浏览器的驱动。

· 浏览器驱动中包含了一个HTTP Server,用来接收这些http请求。

· HTTP Server接收到请求后根据请求来具体操控对应的浏览器。

浏览器执行具体的测试步骤

  浏览器将步骤执行结果返回给HTTP Server。HTTP Server又将结果返回给Selenium的脚本,如果是错误的http代码我们就会在控制台看到对应的报错信息。

为什么使用HTTP协议呢?

因为HTTP协议是一个浏览器和Web服务器之间通信的标准协议,而几乎每一种编程语言都提供了丰富的http libraries,这样就可以方便的处理客户端Client和服务器Server之间的请求request及响应response,WebDriver的结构中就是典型的C/S结构,WebDriver API相当于是客户端,而小小的浏览器驱动才是服务器端。

WebDriver基于的协议:JSON Wire protocol。

JSON Wire protocol是在http协议基础上,对http请求及响应的body部分的数据的进一步规范。

我们知道在HTTP请求及响应中常常包括以下几个部分:http请求方法、http请求及响应内容body、http响应状态码等。

常见的http请求方法:

  GET:用来从服务器获取信息。比如获取网页的标题信息。

  POST:向服务器发送操作请求。比如findElement,Click等。

http响应状态码:

在WebDriver中为了给用户以更明确的反馈信息,提供了更细化的http响应状态码,比如:

7:NoSuchElement

11:ElementNotVisible

200:Everything OK

现在到了最关键的http请求及响应的body部分了:

body部分主要传送具体的数据,在WebDriver中这些数据都是以JSON的形式存在并进行传送的,这就是JSON Wire protocol。

Selenium 是将各个浏览器的API封装成" Selenium自己设计定义的协议,名字叫做The WebDriver Wire Protocol " 的webdriver API

操作层面

  1、测试人员编写UI自动化测试脚本(java,python等等),运行脚本后,程序会打开指定的webdriver浏览器。

webdriver浏览器作为一个remote-server 接受脚本的命令,同时webservice会打开一个端口:http://localhost:9515 浏览器则会监听这个端口。

2、webservice会将脚本语言翻译成json格式传递给浏览器执行操作命令。

逻辑层面:

  1、测试人员执行测试脚本后,就创建了一个session, 通过http 请求向webservice发送了restfull的请求。

  2、webservice翻译restfull的请求为浏览器能懂的脚本,然后接受脚本执行结果。

  3、webservice将结果进行封装--json 给到客户端client/测试脚本 ,然后client就知道操作是否成功,同时测试也可以进行校验了。

我们可以验证一下:

下载好chromedriver,放到环境变量里,注意要和chrome浏览器版本对上,然后执行chromedriver

可以看到,会启动一个server, 并开启端口9515:

andersons-iMac:~ anderson$ chromedriver

Starting ChromeDriver 2.39.562713 (dd642283e958a93ebf6891600db055f1f1b4f3b2) on port 9515

Only local connections are allowed.

GVA info: Successfully connected to the Intel plugin, offline Gen9

强调了只允许本地连接。前面已经提过了,乘客向司机发一个请求,行为是构造一个http请求。构造的请求是这样子的:

请求方式 :POST

请求地址 :http://localhost:9515/session

请求body :

capabilities = {"capabilities": {"alwaysMatch": {"browserName": "chrome"},"firstMatch": [{}]},"desiredCapabilities": {"platform": "ANY","browserName": "chrome","version": "","chromeOptions": {"args": [],"extensions": []}}}我们可以尝试使用python requests 向 ChromeDriver发送请求import requestsimport jsonsession_url = 'http://localhost:9515/session'session_pars = {"capabilities": {"firstMatch": [{}], \"alwaysMatch": {"browserName": "chrome",\"platformName": "any", \"goog:chromeOptions": {"extensions": [], "args": []}}}, \"desiredCapabilities": {"browserName": "chrome", \"version": "", "platform": "ANY", "goog:chromeOptions": {"extensions": [], "args": []}}}r_session = requests.post(session_url,json=session_pars)print(json.dumps(r_session.json(),indent=2))结果:{"sessionId": "44fdb7b1b048a76c0f625545b0d2567b","status": 0,"value": {"acceptInsecureCerts": false,"acceptSslCerts": false,"applicationCacheEnabled": false,"browserConnectionEnabled": false,"browserName": "chrome","chrome": {"chromedriverVersion": "2.40.565386 (45a059dc425e08165f9a10324bd1380cc13ca363)","userDataDir": "/var/folders/yd/dmwmz84x5rj354qkz9rwwzbc0000gn/T/.org.chromium.Chromium.RzlABs"},"cssSelectorsEnabled": true,"databaseEnabled": false,"handlesAlerts": true,"hasTouchScreen": false,"javascriptEnabled": true,"locationContextEnabled": true,"mobileEmulationEnabled": false,"nativeEvents": true,"networkConnectionEnabled": false,"pageLoadStrategy": "normal","platform": "Mac OS X","rotatable": false,"setWindowRect": true,"takesHeapSnapshot": true,"takesScreenshot": true,"unexpectedAlertBehaviour": "","version": "71.0.3578.80","webStorageEnabled": true}}

如何打开一个网页,类似driver.get(url)

那么构造的请求是:

请求方式 :POST

请求地址 :http://localhost:9515/session/:sessionId/url

注意:上述地址中的 ":sessionId"

要用启动浏览器的请求返回结果中的sessionId的值

例如:我刚刚发送请求,启动浏览器,返回结果中"sessionId": "44fdb7b1b048a76c0f625545b0d2567b"  

然后请求的URL地址

请求地址:http://localhost:9515/session/b2801b5dc58b15e76d0d3295b04d295c/url

请求body :{"url": "https://www.baidu.com", "sessionId": "44fdb7b1b048a76c0f625545b0d2567b"}

即:

 import requestsurl = 'http://localhost:9515/session/44fdb7b1b048a76c0f625545b0d2567b/url'pars = {"url": "https://www.baidu.com", "sessionId": "44fdb7b1b048a76c0f625545b0d2567b"}r = requests.post(url,json=pars)print(r.json())

如何定位元素,类似driver.finde_element_by_xx:

请求方式 :POST

请求地址 :http://localhost:9515/session/:sessionId/element

注意:上述地址中的 ":sessionId"

要用启动浏览器的请求返回结果中的sessionId的值。

例如:我刚刚发送请求,启动浏览器,返回结果中"sessionId": "b2801b5dc58b15e76d0d3295b04d295c"  

然后我构造 查找页面元素的请求地址

请求地址:http://localhost:9515/session/b2801b5dc58b15e76d0d3295b04d295c/element

请求body :{"using": "css selector", "value": ".postTitle a", "sessionId": "b2801b5dc58b15e76d0d3295b04d295c"}

即:

import requests

url = 'http://localhost:9515/session/b2801b5dc58b15e76d0d3295b04d295c/element'

pars = {"using": "css selector", "value": ".postTitle a", "sessionId": "b2801b5dc58b15e76d0d3295b04d295c"}

r = requests.post(url,json=pars)

print(r.json())

如何操作元素:类似click()

请求方式 :POST

请求地址 :http://localhost:9515/session/:sessionId/element/:id/click

注意:上述地址中的 ":sessionId"

要用启动浏览器的请求返回结果中的sessionId的值

:id 要用元素定位请求后返回ELEMENT的值

例如:我刚刚发送请求,启动浏览器,返回结果中"sessionId": "b2801b5dc58b15e76d0d3295b04d295c"  

元素定位,返回ELEMENT的值"0.11402119390850629-1"

然后我构造 点击页面元素的请求地址

请求地址:http://localhost:9515/session/b2801b5dc58b15e76d0d3295b04d295c/element/0.11402119390850629-1/click

请求body :{"id": "0.11402119390850629-1", "sessionId": "b2801b5dc58b15e76d0d3295b04d295c"}

即:

import requestsurl = 'http://localhost:9515/session/b2801b5dc58b15e76d0d3295b04d295c/element/0.11402119390850629-1/click'pars ={"id": "0.5930642995574296-1", "sessionId": "b2801b5dc58b15e76d0d3295b04d295c"}r = requests.post(url,json=pars)print(r.json())

 从上面可以看出来,UI自动化,其实也可以写成API自动化。

  只是,只是

  好繁琐,没有封装好的wedriver指令好用,有点脱裤子放屁的感觉。

  我们来写段代码感觉一下:

  import requestsimport timecapabilities = {"capabilities": {"alwaysMatch": {"browserName": "chrome"},"firstMatch": [{}]},"desiredCapabilities": {"platform": "ANY","browserName": "chrome","version": "","chromeOptions": {"args": [],"extensions": []}}}

# 打开浏览器 http://127.0.0.1:9515/session

res = requests.post('http://127.0.0.1:9515/session', json=capabilities).json()

session_id = res['sessionId']

# 打开百度

requests.post('http://127.0.0.1:9515/session/%s/url' % session_id,

              json={"url": "http://www.baidu.com", "sessionId": session_id})

time.sleep(3)

# 关闭浏览器,删除session

requests.delete('http://127.0.0.1:9515/session/%s' % session_id, json={"sessionId": session_id})

其实搞懂真正的原理,也就是为了方便解决问题,在debug的时候,更方便的查看和解决问题。

当然,如果在接口自动化里面也需要调用少量的UI自动化,可以考虑这种方式。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

相关文章:

selenium/webdriver运行原理与机制

最近在看一些底层的东西。driver翻译过来是驱动,司机的意思。如果将webdriver比做成司机,竟然非常恰当。 我们可以把WebDriver驱动浏览器类比成出租车司机开出租车。在开出租车时有三个角色: 乘客:他/她告诉出租车司机去哪里&a…...

论文阅读[121]使用CAE+XGBoost从荧光光谱中检测和识别饮用水中的有机污染物

【论文基本信息】 标题:Detection and Identification of Organic Pollutants in Drinking Water from Fluorescence Spectra Based on Deep Learning Using Convolutional Autoencoder 标题译名:基于使用卷积自动编码器的深度学习,从荧光光谱…...

Juniper SRX PPPoE配置

直接上配置脚本 6号口接运营商进行拨号 ---------- set interfaces ge-0/0/6 unit 0 encapsulation ppp-over-ether set interfaces ge-0/0/6 description "Connect_to_Modem" set interfaces pp0 unit 0 pppoe-options underlying-interface ge-0/0/6.0 set inte…...

虚拟仪器软件结构VISA

1、什么是VISA VISA是虚拟仪器软件结构(Virtual Instrument Software Architectuere)的简称,是由VXI plug & play系统联盟所统一制定的I/O接口软件标准及其相关规范的总称。一般称这个I/O函数库为VISA库(用于仪器编程的标准I/O函数库)。…...

/etc/init.d/functions: Syntax error: “(“ unexpected (expecting “done“)

一.问题描述: ubuntu系统安装服务时报错: 二.问题解析: Ubuntu安装时默认使用dash,shell脚本命令失败,需要安装bash来运行,长期解决该问题就是重新配置dash 三:问题解决: sudo dpkg-reconfi…...

Google/微端/Amazon/IBM四个厂家在分布式里面提供的服务总结

1.背景 最近在复习分布式的课程,发现总有四家公司——Google/微端/Amazon/IBM绕不过去,而他们又开发了许许多多的服务和架构,需要去记忆,于是乎就整理了一下他们提供的服务 2.Google提供的服务 (1)GFS(Go…...

计网:第一章 概述

目录 1.1计算机网络在信息时代作用 1.2因特网概述 1.3三种交换方式 1.4计算机网络的定义和分类 1.5计算机网络的性能指标 1.6计算机网络的体系结构 基于湖科大教书匠b站计算机网络教学视频以及本校课程老师ppt 整合出的计算机网络学习笔记 根据文章目录,具体内…...

RT-DETR算法优化改进:新颖的多尺度卷积注意力(MSCA),即插即用,助力小目标检测 | NeurIPS2022

💡💡💡本文独家改进: 多尺度卷积注意力(MSCA),有效地提取上下文信息,新颖度高,创新十足。 1)代替RepC3进行使用; 2)MSCAAttention直接作为注意力进行使用; 推荐指数:五星 RT-DETR魔术师专栏介绍: https://blog.csdn.net/m0_63774211/category_12497375.ht…...

基于遗传算法改进的GRNN多输入多输出回归预测,基于多目标遗传算法+GRNN的帕累托前沿求解,基于遗传工具箱调用GRNN模型的多目标求解

目录 背影 遗传算法的原理及步骤 基本定义 编码方式 适应度函数 运算过程 代码 结果分析 展望 完整代码下载链接:grnn多输入多输出训练测试,遗传算法改进grnn神经网络,NSGA-2多目标遗传算法,多目标遗传算法和grnn结合优化资源-CSDN文库 https://download.csdn.net/downloa…...

vue2按需导入Element(vite打包)

1.安装element 说明:-S是生产依赖。 npm install element-ui2 -S 2.安装babel-plugin-component 说明:-D是开发模式使用。 npm install babel-plugin-component -D 3. vite.config.js 说明:借助 babel-plugin-component ,我们可…...

力扣117双周赛

第 117 场双周赛 给小朋友们分糖果 I 同T2 给小朋友们分糖果 II 数学 class Solution { public:long long distributeCandies(int n, int limit) {long long ans 0;for (int i 0; i < min(n, limit); i) {if (n - i < limit) {ans n - i 1;} else if (n - i <…...

SPI简介及FPGA通用MOSI模块实现

简介 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外围设备接口&#xff09;通讯协议&#xff0c;是Motorola公司提出的一种同步串行接口技术。是一种高速、全双工、同步通信总线。在芯片中只占用四根管脚用来控制及数据传输。 优缺点&#xff1a; SPI通讯协…...

K8S篇之K8S详解

一、K8S简介 k8s全称kubernetes&#xff0c;是为容器服务而生的一个可移植容器的编排管理工具。k8s目前已经主导了云业务流程&#xff0c;推动了微服务架构等热门技术的普及和落地。 k8s是自动化容器操作的开源平台。这些容器操作包括&#xff1a;部署、调度和节点集群间扩展。…...

进博会再现上亿大单 EZZ携手HIC海橙嗨选签署2024年度合作备忘录

正在举行的第六届中国国际进口博览会上&#xff0c;再现上亿大单。11月6日&#xff0c;在澳大利亚新南威尔士州政府代表的见证下&#xff0c;澳交所基因组龙头上市公司EZZ生命科学和中国跨境社交电商龙头HIC海橙嗨选签署2024合作备忘录&#xff0c;在未来的一年&#xff0c;EZZ…...

深度学习基于python+TensorFlow+Django的花朵识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 花朵识别系统&#xff0c;基于Python实现&#xff0c;深度学习卷积神经网络&#xff0c;通过TensorFlow搭建卷积神经…...

Azure 机器学习 - 机器学习中的企业安全和治理

目录 限制对资源和操作的访问网络安全性和隔离数据加密数据渗透防护漏洞扫描审核和管理合规性 在本文中&#xff0c;你将了解可用于 Azure 机器学习的安全和治理功能。 如果管理员、DevOps 和 MLOps 想要创建符合公司策略的安全配置&#xff0c;那么这些功能对其十分有用。 通过…...

Unity - 各向异性 - 丝绸材质

文章目录 目的环境主观美术效果的[假]丝绸基于物理的方式ProjectPBR filament web captureReferences 目的 拾遗&#xff0c;备份 环境 Unity : 2020.3.37f1 Pipeline : Builtin Rendering Pipeline 主观美术效果的[假]丝绸 非常简单 : half specualr pow(1 - NdotV, _Edg…...

MySQL中UUID主键的优化

UUID&#xff08;Universally Unique IDentifier 通用唯一标识符&#xff09;&#xff0c;是一种常用的唯一标识符&#xff0c;在MySQL中&#xff0c;可以利用函数uuid()来生产UUID。因为UUID可以唯一标识记录&#xff0c;因此有些场景可能会用来作为表的主键&#xff0c;但直接…...

Python实现WOA智能鲸鱼优化算法优化BP神经网络分类模型(BP神经网络分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 鲸鱼优化算法 (whale optimization algorithm,WOA)是 2016 年由澳大利亚格里菲斯大学的Mirjalili 等提…...

Rust语言代码示例

安装Rust语言&#xff0c;然后创建一个新的Rust项目。接下来&#xff0c;你需要安装一个名为"requests"的Rust包&#xff0c;这个包可以帮助你发送请求。然后&#xff0c;你需要安装一个名为"rust-crawler"的Rust包&#xff0c;这个包可以帮助你编写爬虫程…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...