Selenium 底层实现原理详解

Selenium 简介

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

Selenium 原理

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.Firefox()
driver.get('https://www.baidu.com')

打印日志如下:

DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:61123/session {"desiredCapabilities": {"goog:chromeOptions": {"args": [], "extensions": []}, "version": "", "platform": "ANY", "browserName": "chrome"}, "capabilities": {"alwaysMatch": {"goog:chromeOptions": {"args": [], "extensions": []}, "browserName": "chrome", "platformName": "any"}, "firstMatch": [{}]}}
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): 127.0.0.1:61123
DEBUG:urllib3.connectionpool:http://127.0.0.1:61123 "POST /session HTTP/1.1" 200 888
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:61123/session/5f34300c89d868afb8907145fea1639d/url {"sessionId": "5f34300c89d868afb8907145fea1639d", "url": "https://www.baidu.com"}
DEBUG:urllib3.connectionpool:http://127.0.0.1:61123 "POST /session/5f34300c89d868afb8907145fea1639d/url HTTP/1.1" 200 72
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

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

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

# coding=utf-8
import requests


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

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

        # 发送求清
        response_session = requests.post(driver_url, json=driver_value)
        # 获取返回的 sessionId
        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/')

我是「Super于」,立志做一个每天都有正反馈的人!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章