selenium/webdriver运行原理与机制

这篇具有很好参考价值的文章主要介绍了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 requests

  import json

  session_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 requests

  url = '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 requests

  url = '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 requests

  import time

  capabilities = {

      "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自动化,可以考虑这种方式。文章来源地址https://www.toymoban.com/news/detail-491761.html

到了这里,关于selenium/webdriver运行原理与机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • selenium + robotframework的运行原理

    1、点击ride界面启动用例执行时,首先会调用脚本 2、打开pybot脚本查看内容、 3、打开robot包下面的run文件,我们可以看到信息 run文件内容 程序启动的入口, sys.agv所表达的含义是:sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个“外部”很关键,所以那些试图从代

    2024年04月23日
    浏览(40)
  • 微信小程序运行原理揭秘:高效的更新机制

    微信小程序运行机制 官方文档描述的很详细,所以这里只介绍主要的相关概念。 小程序启动后,界面被展示给用户,此时小程序处于 前台 状态。 当用户点击右上角按钮关闭小程序,或者按了设备 Home 键离开微信时,小程序并没有完全终止运行,而是进入了 后台 状态,小程

    2024年02月05日
    浏览(38)
  • 【JavaWeb】Tomcat底层机制和Servlet运行原理

    🎄欢迎来到@dandelionl_的csdn博文,本文主要讲解Java web中Tomcat底层机制和Servlet的运行原理的相关知识🎄 🌈我是dandelionl_,一个正在为秋招和算法竞赛做准备的学生🌈 🎆喜欢的朋友可以关注一下,下次更新不迷路🎆  Ps: 月亮越亮说明知识点越重要 (重要性或者难度越大)🌑🌒

    2024年02月16日
    浏览(56)
  • Apollo规划模块代码学习(1): 算法架构原理、运行机制一文详解

    Apollo开源自动驾驶平台中,高清地图模块提供了每个在线模块都可以访问的高清地图。感知和定位模块提供了必要的动态环境信息,可以在预测模块中进一步用于预测未来的环境状态。运动规划模块考虑所有信息,以生成安全平滑的轨迹,并将其输入车辆控制模块。 目前Ap

    2024年01月25日
    浏览(46)
  • “深入剖析JVM内部机制:探索Java虚拟机的运行原理“

    标题:深入剖析JVM内部机制:探索Java虚拟机的运行原理 摘要:本文将深入探讨Java虚拟机(JVM)的内部机制,包括类加载、内存管理、垃圾回收、即时编译等关键概念和原理,帮助开发者更好地理解JVM的运行机制。 正文: 一、类加载机制 Java虚拟机通过类加载机制将字节码文

    2024年02月14日
    浏览(60)
  • “深入探索JVM内部机制:理解Java虚拟机的运行原理“

    标题:深入探索JVM内部机制:理解Java虚拟机的运行原理 摘要:本篇博客将深入探索Java虚拟机(JVM)的内部机制,帮助读者理解JVM的运行原理。我们将介绍JVM的组成结构,包括类加载器、运行时数据区域和执行引擎,并通过示例代码解释这些概念的具体应用。 正文: 一、J

    2024年02月11日
    浏览(45)
  • 【jvm系列-08】精通String字符串底层原理和运行机制(详解)

    JVM系列整体栏目 内容 链接地址 【一】初识虚拟机与java虚拟机 https://blog.csdn.net/zhenghuishengq/article/details/129544460 【二】jvm的类加载子系统以及jclasslib的基本使用 https://blog.csdn.net/zhenghuishengq/article/details/129610963 【三】运行时私有区域之虚拟机栈、程序计数器、本地方法栈 https

    2023年04月17日
    浏览(93)
  • web自动化测试系列之selenium的运行原理和常用方法介绍(二)

    在上文中我们编写了一段简单的代码 ,可以驱动浏览器访问百度并搜索 。这里我们再把这段代码再拿来加以说明 。 如果你是初次接触它 ,你可能会想 ,这段代码是怎么驱动浏览器运行的了 ?要知道这个问题的答案 ,就必须搞清楚以下3个问题 。 它(selenium)的运行原

    2024年04月11日
    浏览(43)
  • Selenium WebDriver 开发实战

    WebDriver提供的一系列对象定位方法,获取元素,实现测试用例。现在我们先来写一些调试代码,看看是否能成功驱动浏览器执行操作。 各行代码的作用分别如下: 之前已经安装了Selenium,第1行用于从Selenium库中导入webdriver模块。Selenium库中有common和webdriver两个模块,common模块

    2024年01月17日
    浏览(42)
  • Python + Selenium WebDriver

    Python + Selenium WebDriver 一、搭建环境步骤 1、安装 python3.x (windows xp 不支持 python3.5+) 2、设置环境变量 path(安装时候也可以解决 勾上 add python.ext to path) 3、安装Selenium 用pip命令安装 pip install -U selenium 4、路径,pip可能定位不到,pip也可能定位到别的文件夹(perl) 方案:cd

    2024年02月12日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包