继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Selenium Manager详解

2024-09-11 13:50:53191浏览

城下秋草

1实战 · 27手记 · 16推荐
TA的实战

Selenium诞生于2004年,以其开源、功能全面长期以来长期排名Web 自动化测试工具领域的Top1,是目前最主流的Web自动化测试工具,而Selenium的核心Webdriver 更是作为W3C的通行标准,被各类工具广泛参照。可以说是目前web自动化测试的事实标准。

Selenium 4带来的变化

Selenium本身经过多年的演进,目前已经发布到V4.24版本。 虽然目前网上还广泛流传V3版本相关的用法和资料,但Selenium 4 其实是一个非常大的更新版本。它的几个核心组件都进行的极大程度的重构。

  • WebDriver 从原先的Json Wire Protocol 切换为了W3C的标准定义
  • Selenium IDE 完成重构和功能优化
  • Selenium Grid 完成重构,支持更灵活的云服务架构

此外Selenium 4中还引入了一个很重要的工具,也就是本篇我们要重点来介绍的Selenium Manager(实际是V4.6才引入,到V4.12 功能才基本完备

原先的浏览器驱动方式带来的问题

要了解Selenium Manager,我们还是要先了解下Selenium的工作原理。

Selenium工作原理

下图是官网给的Selenium本地运行的基本架构。
Pasted-20240908.png

可以看到,Selenium实际上完成自动化,是通过webdriver协议驱动不同类型的浏览器(Chrome、Firefox、IE、Edge、Safari等)完成指定的动作,以此达到自动化执行的目的。

而驱动浏览器的关键,是和浏览器对应的浏览器Driver驱动,比如Chrome对应的ChromeDriver, FireFox对应的GecoDriver等。

而Selenium本身,则是基于WebDriver协议和浏览器Driver完成交互。

导致的问题

这个架构和工作原理虽然清晰,但是有一个问题,就是浏览器的版本是不断更新的。而浏览器驱动版本需要和浏览器版本匹配,不匹配的驱动和浏览器版本,共同工作可能存在各种预期外的异常,所以Selenium要正常工作,再用Selenium库完成编码前,首先就是要保证浏览器驱动和浏览器版本的部署和匹配。

但浏览器版本和对应的驱动,通常都是由浏览器厂商维护的。

所以这里的自动化测试环境准备就会变得比较复杂,要安装对应被测版本的浏览器,同时还要找到对应这个版本的驱动,再把相关路径配置给Selenium,然后Selenium才能完成正常的驱动。

此外,浏览器的版本,一般还有自动更新功能,可能在用户没感知的情况,其实版本已经变化了,但此时驱动版本并不会同步更新,所以也导致驱动和浏览器版本不匹配的潜在问题。

这个问题,其实长期没有得到很好地解决,Selenium 3和Selenium 4的早期版本,我们部署Selenium 自动化环境,浏览器版本和驱动版本的获取和匹配一直是一个比较麻烦的工作,也因此劝退了不少自动化测试小白。

Chrome对驱动问题的应对

既然这个问题由来已久,浏览器厂商其实也意识到驱动和浏览器版本不匹配,给自动化测试带来的困扰。

以Chrome为例,我们去到 ChromeDriver官方下载 网址的话,会看到这样的页面

Pasted-20240910.png

可以看到,这里对Chrome Driver的下载只提供到了114版本,而最新的Chrome其实已经到了128版本。
对于115版本以后,Chrome浏览器其实调整了driver的发布策略,也就是Chrome driver会跟随 Chrome for Testing 版本同步发布。严格保证driver和浏览器版本的同步匹配。

那这里为什么有一个Chrome for Testing版本呢?
Pasted-20240910-1.png
我们之前提到,浏览器版本,会有自动更新,如果进行自动更新,driver版本不会同步更新,所以导致dirver和浏览器的不匹配。

所以Chrome for Testing与正式版本的主要区别,其实就是 for Testing版本是不会进行自动更新的。

这样,再加上版本号和浏览器版本的共用,就能很方便地保证浏览器和驱动的一致。

Selenium应对驱动匹配问题的解决方案

那上面是浏览器对驱动匹配问题给出的解决方法,但其实还是没有完全解决浏览器、Driver需要分别获取和指定的问题。那么Selenium官方对这个问题的解决方案,就是Selenium Manager。它其实是一个包含在Selenium库中,无需额外安装的可执行程序。

Pasted-20240910-2.png

我们目前使用Selenium V4来执行一个简单的自动化测试脚本的话:

比如通过百度,搜索城下秋草 测试, 代码如下:

from selenium import webdriver  
from selenium.webdriver.common.by import By  
from time import sleep
  
def test_baidu_search():  
    option = webdriver.ChromeOptions()  
    option.browser_version = '117'  
    driver = webdriver.Chrome(options=option)  
  
    driver.get("https://www.baidu.com")  
    driver.find_element(By.ID,'kw').send_keys('城下秋草 测试')  
    sleep(2)  
    driver.find_element(By.ID,'su').click()  
    sleep(3)  
    driver.close()

只要安装了Selenium库,执行的时候,就可以正常地驱动, 并不需要特别地去获取驱动和配置。

run.gif

Selenium 4 启动自动化执行源码分析

这里我们从Selenium的Python源码来分析下它的启动过程:

driver = webdriver.Chrome(options=option)

这行代码其实会调用Slenium库中Chromium基础浏览器的webdriver初始化代码,位置在.venv/Lib/site-packages/selenium/webdriver/chromium/webdriver.py

初始化时,可以看到,会通过DriverFinder方法来获取浏览器和Driver的路径

finder = DriverFinder(self.service, options)  
if finder.get_browser_path():  
    options.binary_location = finder.get_browser_path()  
    options.browser_version = None  
  
self.service.path = finder.get_driver_path()  
self.service.start()

而获取路径的方法,其实就是调用了SeleniumManager模块的binary_paths方法

def get_browser_path(self) -> str:  
    return self._binary_paths()["browser_path"]  
  
def get_driver_path(self) -> str:  
    return self._binary_paths()["driver_path"]  
  
def _binary_paths(self) -> dict:  
    if self._paths["driver_path"]:  
        return self._paths  
  
.
.
.


            output = SeleniumManager().binary_paths(self._to_args())  
.
.
.
    return self._paths

而SeleniumManager模块,则会执行SeleniumManager的二进制程序,根据相关参数,获取浏览器和驱动版本。

def _run(args: List[str]) -> dict:  
    """Executes the Selenium Manager Binary.  
  
    :Args:     - args: the components of the command being executed.    :Returns: The log string containing the driver location.    """    command = " ".join(args)  
    logger.debug("Executing process: %s", command)  
    try:  
        if sys.platform == "win32":  
            completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)  
        else:  
            completed_proc = subprocess.run(args, capture_output=True)  
        stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")  
        stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")  
        output = json.loads(stdout) if stdout != "" else {"logs": [], "result": {}}  
    except Exception as err:  
        raise WebDriverException(f"Unsuccessful command executed: {command}") from err  
  
    SeleniumManager._process_logs(output["logs"])  
    result = output["result"]  
    if completed_proc.returncode:  
        raise WebDriverException(  
            f"Unsuccessful command executed: {command}; code: {completed_proc.returncode}\n{result}\n{stderr}"  
        )  
    return result

所以,目前的Selenium 4版本执行时,会通过SeleniumManager程序来确定需要的浏览器和对应的driver版本。

Selenium Manager 命令行程序

而通过SeleniumManager,根据我们配置的浏览器类型和版本,它可以自动的匹配相关的driver版本,并自行联网,获取相关驱动和浏览器版本的文件,供Selenium调用。
比如上例中,我们指定了浏览器版本为 117, 执行以后,在用户目录的 .cache\selenium目录下其实就会保存下载的浏览器和对应的驱动版本。下图是当前执行更新的117 版本的驱动。
Pasted-20240910-3.png

这里Selenium调用的是Selenium-manager这个命令行程序

我们可以直接执行这个程序,加上--help看一下支持的参数

selenium-manager 0.4.24
Selenium Manager is a CLI tool that automatically manages the browser/driver infrastructure required by Selenium.


Usage: selenium-manager [OPTIONS]
Options:
      --browser <BROWSER>
          Browser name (chrome, firefox, edge, iexplorer, safari, safaritp, or webview2)
      --driver <DRIVER>
          Driver name (chromedriver, geckodriver, msedgedriver, IEDriverServer, or safaridriver)
      --grid [<GRID_VERSION>]
          Selenium Grid. If version is not provided, the latest version is downloaded
      --driver-version <DRIVER_VERSION>
          Driver version (e.g., 106.0.5249.61, 0.31.0, etc.)
      --browser-version <BROWSER_VERSION>
          Major browser version (e.g., 105, 106, etc. Also: beta, dev, canary -or nightly-, and esr -in Firefox- are accepted)
      --browser-path <BROWSER_PATH>
          Browser path (absolute) for browser version detection (e.g., /usr/bin/google-chrome, "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", "C:\Program Files\Google\Chrome\Application\chrome.exe")
      --driver-mirror-url <DRIVER_MIRROR_URL>
          Mirror for driver repositories (e.g., https://registry.npmmirror.com/-/binary/chromedriver/)
      --browser-mirror-url <BROWSER_MIRROR_URL>
          Mirror for browser repositories
      --output <OUTPUT>
          Output type: LOGGER (using INFO, WARN, etc.), JSON (custom JSON notation), SHELL (Unix-like), or MIXED (INFO, WARN, DEBUG, etc. to stderr and minimal JSON to stdout) [default: LOGGER]
      --os <OS>
          Operating system (i.e., windows, linux, or macos)
      --arch <ARCH>
          System architecture (i.e., x32, x64, or arm64)
      --proxy <PROXY>
          HTTP proxy for network connection (e.g., https://myproxy.net:8080)
      --timeout <TIMEOUT>
          Timeout for network requests (in seconds) [default: 300]
      --ttl <TTL>
          TTL (time-to-live) for discovered versions (online) of drivers and browsers [default: 3600]
      --cache-path <CACHE_PATH>
          Local folder used to store downloaded assets (drivers and browsers), local metadata, and configuration file [default: ~/.cache/selenium]
      --clear-cache
          Clear cache folder (~/.cache/selenium)
      --clear-metadata
          Clear metadata file (~/.cache/selenium/selenium-manager.json)
      --debug
          Display DEBUG messages
      --trace
          Display TRACE messages
      --log-level <LOG_LEVEL>
          Level for output messages. The possible values are: info, debug, trace, warn, error
      --offline
          Offline mode (i.e., disabling network requests and downloads)
      --force-browser-download
          Force to download browser (even when browser is already in the system)
      --avoid-browser-download
          Avoid to download browser (even when browser-version is specified)
      --language-binding <LANGUAGE_BINDING>
          Selenium language bindings that invokes Selenium Manager (e.g., Java, JavaScript, Python, DotNet, Ruby)
      --avoid-stats
          Avoid sends usage statistics to plausible.io
  -h, --help
          Print help
  -V, --version
          Print version

我们可以执行看一下这里输出信息,其实selenium在执行时就是调用的这个命令行程序

>selenium-manager.exe --browser firefox --debug    #debug参数显示详细输出

[2024-09-10T13:35:56.007Z DEBUG] geckodriver not found in PATH

# 首先在系统Path路径中根据指定的浏览器判断是否存在驱动

[2024-09-10T13:35:56.010Z DEBUG] firefox not found in PATH

# 同样根据Path路径中是否包含firefox浏览器安装路径

[2024-09-10T13:35:56.010Z DEBUG] Running command: REG QUERY HKCU\Software\Mozilla\Mozilla Firefox /v CurrentVersion
[2024-09-10T13:35:56.034Z DEBUG] Output: ""
[2024-09-10T13:35:56.036Z DEBUG] firefox not found in the system

# 通过注册表查找firefox浏览器安装路径

[2024-09-10T13:35:56.037Z DEBUG] Required browser: firefox 130.0

-- 未指定浏览器版本,根据联网信息获取最新版本

[2024-09-10T13:35:56.037Z DEBUG] Downloading firefox 130.0 from https://ftp.mozilla.org/pub/firefox/releases/130.0/win64/en-US/Firefox%20Setup%20130.0.exe

# 从官网下载

[2024-09-10T13:36:13.320Z DEBUG] firefox 130.0 is available at C:\Users\Administrator\.cache\selenium\firefox\win64\130.0\firefox.exe

# 完成下载

[2024-09-10T13:36:14.367Z DEBUG] Valid geckodriver versions for firefox 130: ["0.35.0", "0.34.0"]

# 获取可用driver 版本

[2024-09-10T13:36:14.369Z DEBUG] Required driver: geckodriver 0.35.0
[2024-09-10T13:36:14.372Z DEBUG] Downloading geckodriver 0.35.0 from https://github.com/mozilla/geckodriver/releases/download/v0.35.0/geckodriver-v0.35.0-win64.zip

# 下载对应driver

[2024-09-10T13:36:18.238Z INFO ] Driver path: C:\Users\Administrator\.cache\selenium\geckodriver\win64\0.35.0\geckodriver.exe
[2024-09-10T13:36:18.239Z INFO ] Browser path: C:\Users\Administrator\.cache\selenium\firefox\win64\130.0\firefox.exe

# 输出browser和driver路径,其实selenium调用时的返回值就是这个信息

而除了Browser和Driver外,Selenium-manager其实还支持grid版本的下载。通过--grid 参数就可以直接下载grid的最新版本。

> selenium-manager.exe --grid --debug
[2024-09-10T13:47:41.793Z DEBUG] Sending stats to Plausible: Props { browser: "grid", browser_version: "", os: "windows", arch: "amd64", lang: "", selenium_version: "4.24" }
[2024-09-10T13:47:41.795Z DEBUG] grid not found in the system
[2024-09-10T13:47:43.667Z DEBUG] Required driver: selenium-server 4.24.0
[2024-09-10T13:47:43.669Z DEBUG] Downloading selenium-server 4.24.0 from https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.24.0/selenium-server-4.24.0.jar
[2024-09-10T13:47:51.547Z INFO ] Driver path: C:\Users\Administrator\.cache\selenium\grid\4.24.0\selenium-server-4.24.0.jar

通过以上介绍,可以看出,通过引入Selenium-manager,Selenium在环境准备时已经可以非常灵活地实现对浏览器、驱动包括grid server等资源的自动获取和配置,极大提升了使用Selenium的便利性。


更多测试职业进阶知识全方位梳理,可以关注我的新课

❤️ ❤️ ❤️ 测试高级工程师系统养成-高薪就业课 ❤️ ❤️ ❤️

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP