Selenium实现原理

Selenium 是目前主流的用于Web应用程序测试的工具,可以直接运行在浏览器中,就像真正的用户在操作一样。

selenium的实现原理是这样的:

1.运行代码,启动浏览器后,webdriver会将浏览器绑定到特定端口,作为webdriver的remote server;
2.Client(也就是测试脚本)借助ComandExecutor创建sessionId,发送HTTP请求(包括HTTP method, body)给remote server;
3.remote server收到HTTP请求后,调用webdriver完成操作,并将HTTP响应的结果返回给Client。

Selenium工作的过程中有三个角色,

其一便是跟我们最近的自动化测试代码:自动化测试代码发送请求给浏览器的驱动

其二便是浏览器的驱动:每个浏览器都有自己的驱动,均以exe文件形式存在,比如谷歌的chromedriver.exe、火狐的geckodriver.exe、IE的IEDriverServer.exe,

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

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

下面以谷歌浏览器为例:

首先,selenium client 会初始化一个 service 服务,通过 Webdriver 启动浏览器驱动程序 chromedriver.exe

接着通过 RemoteWebDriver 向浏览器驱动程序发送 HTTP 请求,浏览器驱动程序解析请求,并获得 sessionId,如果再次对浏览器操作需携带此 id

接下来打开浏览器,绑定特定的端口,把启动后的浏览器作为 Webdriver 的Remote Server

打开浏览器后,每一条 Selenium 脚本,一个 http 请求会被创建并且发送给浏览器,浏览器执行具体的测试步骤后再将步骤执行结果返回给 Remote Server,Remote Server 又将结果返回给 Selenium 的脚本,如果是错误的 http 代码我们就会在控制台看到对应的报错信息。

WebDriver 和 Selenium-Server 区别

你可能需要,也可能不需要 Selenium Server,取决于你打算如何使用 Selenium-WebDriver。

如果你仅仅需要使用 WebDriver API,那就不需要 Selenium-Server。

如果你所有的测试和浏览器都在一台机器上,那么你仅需要 WebDriver API。WebDriver 将直接操作浏览器。

在有些情况下,你需要使用 Selenium-Server 来配合 Selenium-WebDriver 工作,例如:
你使用 Selenium-Grid 来分发你的测试给多个机器或者虚拟机。
你希望连接一台远程的机器来测试一个特定的浏览器。
你没有使用 Java 绑定(例如 Python, C#, 或 Ruby),并且可能希望使用 HtmlUnit Driver。

底层实现原理

下面先写一个通过火狐浏览器启动百度首页的脚本:

from selenium import webdriver
import logging

logging.basicConfig(level=logging.DEBUG)  # 打印源码中的日志
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

打印日志如下:

DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:63959/session {"capabilities": {"firstMatch": [{}], "alwaysMatch": {"browserName": "chrome", "pageLoadStrategy": "normal", "goog:chromeOptions": {"extensions": [], "args": []}}}}
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:63959
DEBUG:urllib3.connectionpool:http://localhost:63959 "POST /session HTTP/1.1" 200 794
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":{"capabilities":{"acceptInsecureCerts":false,"browserName":"chrome","browserVersion":"102.0.5005.115","chrome":{"chromedriverVersion":"102.0.5005.61 (0e59bcc00cc4985ce39ad31c150065f159d95ad3-refs/branch-heads/5005@{#819})","userDataDir":"C:\\Users\\jeff.xie\\AppData\\Local\\Temp\\scoped_dir15248_1149020991"},"goog:chromeOptions":{"debuggerAddress":"localhost:63963"},"networkConnectionEnabled":false,"pageLoadStrategy":"normal","platformName":"windows","proxy":{},"setWindowRect":true,"strictFileInteractability":false,"timeouts":{"implicit":0,"pageLoad":300000,"script":30000},"unhandledPromptBehavior":"dismiss and notify","webauthn:extension:credBlob":true,"webauthn:extension:largeBlob":true,"webauthn:virtualAuthenticators":true},"sessionId":"a402557c61699397cccbdabf77e06cd1"}} | headers=HTTPHeaderDict({'Content-Length': '794', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:63959/session/a402557c61699397cccbdabf77e06cd1/url {"url": "https://www.baidu.com"}
DEBUG:urllib3.connectionpool:http://localhost:63959 "POST /session/a402557c61699397cccbdabf77e06cd1/url HTTP/1.1" 200 14
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":null} | headers=HTTPHeaderDict({'Content-Length': '14', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

可以看到,首先通过 Webdriver 启动浏览器驱动程序 chromedriver.exe,打开浏览器,并获得 sessionId,然后再向带上 sessionId 向浏览器发送打开百度主页的请求。

下面自己通过 requests 模块来模拟这一系列过程(执行之前首先要打开selenium-server 服务,我是使用的 selenium-server 服务,你也可以使用浏览器服务)
 

首先在cmd中启动selenium-server  服务

 然后再Pycharm中运行以下代码

# coding=utf-8
import requests


class MySelenium:
    def __init__(self):
        self.driver = self.my_webdriver_chrome()

    def my_webdriver_chrome(self):
        '''
        获取driver
        :return:
        '''
        driver_url = 'http://127.0.0.1:4444/wd/hub/session/'
        # 打开浏览器的请求参数
        driver_value = {"capabilities":
                            {"alwaysMatch":
                                 {"browserName": "chrome", }
                             }
                        }

        # 发送求清
        response_session = requests.post(driver_url, json=driver_value)
        # 获取返回的 sessionId
        print(response_session.json())
        # 获取session ID
        my_sessionId = response_session.json()['value']['sessionId']

        return driver_url + my_sessionId

    def my_get(self, url):
        '''
        通过get方式访问网址
        :param url:
        :return:
        '''
        temp_url = self.driver + '/url'
        value = {'url': url}
        requests.post(temp_url, json=value)


if __name__ == '__main__':
    obj_my_selenium = MySelenium()
    obj_my_selenium.my_get('https://www.baidu.com/')

 

在cmd中的log

10:43:36.123 INFO [ActiveSessionFactory.apply] - Capabilities are: {
  "browserName": "chrome"
}
10:43:36.124 INFO [ActiveSessionFactory.lambda$apply$11] - Matched factory org.openqa.selenium.grid.session.remote.ServicedSession$Factory (provider: org.openqa.selenium.chrome.ChromeDriverService)
Starting ChromeDriver 102.0.5005.61 (0e59bcc00cc4985ce39ad31c150065f159d95ad3-refs/branch-heads/5005@{#819}) on port 28904
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
10:43:38.565 INFO [ProtocolHandshake.createSession] - Detected dialect: W3C
10:43:38.594 INFO [RemoteSession$Factory.lambda$performHandshake$0] - Started new session f40b23a4faffac1dadf030c5073f5b7a (org.openqa.selenium.chrome.ChromeDriverService)
 

代码返回的session ID

# 获取返回的 sessionId

print(response_session.json())

{'value': {'sessionId': '287f14c5789390e0570ae8c5ae62dc9f', 'capabilities': {'acceptInsecureCerts': False, 'browserName': 'chrome', 'browserVersion': '102.0.5005.115', 'chrome': {'chromedriverVersion': '102.0.5005.61 (0e59bcc00cc4985ce39ad31c150065f159d95ad3-refs/branch-heads/5005@{#819})', 'userDataDir': 'C:\\Users\\jeff.xie\\AppData\\Local\\Temp\\scoped_dir28400_1955656845'}, 'goog:chromeOptions': {'debuggerAddress': 'localhost:49896'}, 'networkConnectionEnabled': False, 'pageLoadStrategy': 'normal', 'platformName': 'windows', 'proxy': {}, 'setWindowRect': True, 'strictFileInteractability': False, 'timeouts': {'implicit': 0, 'pageLoad': 300000, 'script': 30000}, 'unhandledPromptBehavior': 'dismiss and notify', 'webauthn:extension:credBlob': True, 'webauthn:extension:largeBlob': True, 'webauthn:virtualAuthenticators': True, 'webdriver.remote.sessionid': '287f14c5789390e0570ae8c5ae62dc9f'}}}

每一条 Selenium 脚本,

一个 http 请求会被创建并且发送给浏览器,

浏览器执行具体的测试步骤后再将步骤执行结果返回给 Remote Server,

Remote Server 又将结果返回给 Selenium 的脚本,

如果是错误的 http 代码我们就会在控制台看到对应的报错信息。
 

from selenium import webdriver
import logging
from selenium.webdriver.common.by import By

logging.basicConfig(level=logging.DEBUG)
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
logging.info("Start to test!!!!!!!!!!!!!")
driver.find_element(By.ID,"kw").send_keys("python")
logging.info("Start to click!!!!!!!!!!!!!")
driver.find_element(By.ID,"su").click()
print("OKOKOKO")

我们可以通过log来分析上面的代码具体有什么操作

查找元素并sendkeys执行log

INFO:root:Start to test!!!!!!!!!!!!!

#携带参数发送请求
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:51369/session/adb3143b146fe78c0ee16cdbded4d459/element {"using": "css selector", "value": "[id=\"kw\"]"}

#返回状态码

DEBUG:urllib3.connectionpool:http://localhost:51369 "POST /session/adb3143b146fe78c0ee16cdbded4d459/element HTTP/1.1" 200 88

#响应数据

DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":{"element-6066-11e4-a52e-4f735466cecf":"68c631e2-3c2f-4d21-84cd-09939da46e28"}} | headers=HTTPHeaderDict({'Content-Length': '88', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})

#查找元素完成
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

#发起sendkey请求,携带查找元素时的返回数据
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:51369/session/adb3143b146fe78c0ee16cdbded4d459/element/68c631e2-3c2f-4d21-84cd-09939da46e28/value {"text": "python", "value": ["p", "y", "t", "h", "o", "n"], "id": "68c631e2-3c2f-4d21-84cd-09939da46e28"}
DEBUG:urllib3.connectionpool:http://localhost:51369 "POST /session/adb3143b146fe78c0ee16cdbded4d459/element/68c631e2-3c2f-4d21-84cd-09939da46e28/value HTTP/1.1" 200 14

#执行sendkey动作
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":null} | headers=HTTPHeaderDict({'Content-Length': '14', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})

#执行完成
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

查找元素并click执行log

INFO:root:Start to click!!!!!!!!!!!!!

DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:51369/session/adb3143b146fe78c0ee16cdbded4d459/element {"using": "css selector", "value": "[id=\"su\"]"}
DEBUG:urllib3.connectionpool:http://localhost:51369 "POST /session/adb3143b146fe78c0ee16cdbded4d459/element HTTP/1.1" 200 88
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":{"element-6066-11e4-a52e-4f735466cecf":"52336fcb-f3c8-4c74-a545-2a30ebe94034"}} | headers=HTTPHeaderDict({'Content-Length': '88', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:51369/session/adb3143b146fe78c0ee16cdbded4d459/element/52336fcb-f3c8-4c74-a545-2a30ebe94034/click {"id": "52336fcb-f3c8-4c74-a545-2a30ebe94034"}
DEBUG:urllib3.connectionpool:http://localhost:51369 "POST /session/adb3143b146fe78c0ee16cdbded4d459/element/52336fcb-f3c8-4c74-a545-2a30ebe94034/click HTTP/1.1" 200 14
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":null} | headers=HTTPHeaderDict({'Content-Length': '14', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

OKOKOKO

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Selenium是一种用于支持Web应用程序测试的开源工具,它可以帮助您进行自动化测试。它通过使用驱动程序模拟用户来模拟用户的操作,从而实现自动化。它可以在多种浏览器和操作系统上运行,支持各种编程语言。 ### 回答2: Selenium是一种用于自动化Web浏览器操作的工具。它的原理是通过模拟用户在浏览器中的操作来实现自动化。 首先,Selenium可以与多种浏览器进行交互,如Chrome、Firefox、Safari等。它通过与浏览器驱动程序进行通信来控制浏览器的行为,这些驱动程序通常由浏览器供应商提供。 其次,Selenium可以通过各种编程语言(如Java、Python、C#等)编写脚本来实现自动化。通过调用Selenium提供的API,可以编写代码来模拟用户在浏览器中的交互行为,如点击、输入、滚动等。 另外,Selenium还提供了一组丰富的方法和工具,用于定位和操作Web元素。通过使用特定的选择器或路径,可以定位到浏览器中的元素,如按钮、文本框、链接等。然后,可以使用Selenium提供的方法对这些元素进行各种操作,如点击、输入文本、获取文本等。 最后,Selenium还支持对浏览器进行截屏和处理JavaScript弹窗等高级功能。通过截屏,可以捕捉当前浏览器界面的图像,并用于测试和调试。对于弹出的JavaScript弹窗,Selenium提供了与之交互的方法,可以处理其内容,如接受/拒绝弹窗。 综上所述,Selenium实现自动化的原理主要是通过与浏览器进行交互,并模拟用户在浏览器中的操作来实现自动化。它提供了一组方法和工具,用于定位和操作Web元素,以及处理高级功能,如截屏和JavaScript弹窗。 ### 回答3: Selenium是一个开源的自动化测试工具,用于模拟用户在浏览器上执行操作。它的工作原理可以分为以下几个步骤: 1. 定位元素:Selenium可以通过不同的方式来定位网页上的元素,如ID、类名、标签名、链接文本等。通过定位元素,我们可以操作这些元素进行自动化测试。 2. 执行操作:Selenium可以模拟用户在浏览器上的各种操作,如点击、填写表单、选择下拉框等。这些操作是通过Selenium提供的API来执行的。 3. 等待响应:由于网页加载和响应需要时间,所以在执行操作后,我们需要等待一段时间来获取页面的响应。Selenium提供了不同的等待方式,例如等待固定时间、等待元素可见、等待元素可点击等。 4. 断言验证:在自动化测试中,我们需要验证页面上的一些属性或内容是否符合预期。通过断言,我们可以判断测试是否通过,并做出相应的处理。 5. 输出结果:Selenium可以将测试结果输出为日志文件或HTML报告。这些结果可以用于测试分析和问题定位。 总的来说,Selenium可以通过定位元素、执行操作、等待响应、断言验证和输出结果的方式来实现自动化测试。这使得开发人员可以更方便地进行功能测试、回归测试和性能测试等工作,提高软件质量和开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值