测试老宅男扶摇

导航

Selenium4Web自动化11-分布式测试Grid入门到实战

一、Grid介绍

要在多台计算机上并行运行测试吗? 那么, Grid正是为你准备的.
Selenium Grid允许通过路由命令在远程机器上执行WebDriver脚本,这些命令由客户机发送到远程浏览器实例,如下图所示:

  • WebDriver: 驱动程序是特定于浏览器的,例如 ChromeDriver 对应于谷歌的 Chrome/Chromium, GeckoDriver 对应于 Mozilla 的 Firefox 的,等等。驱动程序在与浏览器相同的系统上运行。 这可能与执行测试本身的系统相同,也可能不同。
  • Selenium Server 或 Selenium Grid: 远程通信也可以使用 Selenium Server 或 Selenium Grid 进行,这两者依次与主机系统上的驱动程序进行通信
  • Test FRAMEWORK(应用框架): WebDriver 有且只有一个任务: 通过上面的任何方法与浏览器通信。WebDriver 对测试一窍不通:它不知道如何比较事物、 断言通过或失败,当然它也不知道报告或 Given/When/Then 语法。这就是各种框架发挥作用的地方。至少你需要一个与绑定语言相匹配的测试框架,比如Python的Pytest,. NET 的 NUnit, Java 的 JUnit, Ruby 的 RSpec 等等。测试框架负责运行和执行 WebDriver 以及测试中相关步骤。

Grid的目标是:

  • 提供在多台机器上并行运行测试的简单方法

  • 允许在不同的浏览器版本上进行测试

  • 启用跨平台测试

二、Selenium Grid快速入门

Quick start

1.先决条件

2.启动Grid

java -jar selenium-server-<version>.jar standalone


启动后,可打开浏览器访问:http://127.0.0.1:4444

3.将WebDriver测试指向http://localhost:4444

您可以如本地一样, 使用远程WebDriver. 主要区别在于需要配置远程WebDriver, 以便可以在不同的计算机上运行测试.
远程WebDriver由两部分组成:客户端和服务端. 客户端是您的WebDriver测试,而服务端仅仅是可以被托管于任何现代Java EE应用服务器的Java Servlet.
要运行远程WebDriver客户端, 我们首先需要连接到RemoteWebDriver. 为此, 我们将URL指向运行测试的服务器的地址. 为了自定义我们的配置, 我们设置了既定的功能. 下面是一个实例化样例, 其指向我们的远程Web服务器 http://localhost:4444的远程WebDriver对象, 并在Chrome上运行测试.

from selenium import webdriver

chrome_options = webdriver.ChromeOptions()
driver = webdriver.Remote(
    command_executor='http://127.0.0.1:4444',
    options=chrome_options
)
driver.get("http://www.baidu.com")
driver.quit()

4.通过打开浏览器http://localhost:4444检查正在运行的测试和可用的功能

要了解关于不同配置选项的更多信息,请参见下面的部分

Grid 模式详解

Grid由六个不同的组件组成,这为您提供了以不同方式部署它的选项。

根据您的需要,您可以单独启动它们中的任一个(分布式的Distributed),并将它们分组到中心(Hub)和节点(Node)中,或在一台机器上集所有于一体(独立的Standalone)

1.Standalone(独立模式)

Standalone将所有Grid组件无缝地组合为一个。以独立模式运行Grid可以在单个进程中使用单个命令获得功能完整的Grid。单机只能在一台机器上运行。
Standalone也是运转Selenium Grid最简单的模式。默认情况下,服务器将监听http://localhost:4444上的RemoteWebDriver请求。默认情况下,服务器将从System PATH(环境变量)中检测可用的驱动程序。

java -jar selenium-server-<version>.jar standalone

在Standalone模式下成功启动Grid之后,将WebDriver测试指向http://localhost:4444。

Standalone模式的常用场景有:

  • 使用RemoteWebDriver在本地开发或调试测试

  • 在推送代码之前运行快速测试套件

  • 在CI/CD工具(GitHub Actions, Jenkins等)中轻松配置Grid。

2.Hub and Node (中心和节点模式)

中心和节点是使用最多的模式,因为它允许:

  • 将不同的机器组合在一个Grid中

    • 例如,使用不同操作系统和/或浏览器版本的机器
  • 使用统一入口点来在不同的环境中运行WebDriver测试

  • 在不破坏Grid的情况下,增加或减少组件

Hub
Hub由以下组件组成:路由器(Router)、分发器(Distributor)、会话映射(Session Map)、新会话队列(New Session Queu)和事件总线(Event Bus)。

java -jar selenium-server-<version>.jar hub

默认情况下,服务器将监听http://localhost:4444上的RemoteWebDriver请求

Node
在启动期间,节点将从System PATH(环境变量)中检测可用的驱动程序。

下面的命令假设Node和Hub运行在同一台机器上

java -jar selenium-server-<version>.jar node

同一机器上的多个节点
Node 1

java -jar selenium-server-<version>.jar node --port 6666


Node 2

java -jar selenium-server-<version>.jar node --port 7777

Node and Hub 在不同的机器上
Hub和Nodes通过HTTP和事件总线Event Bus(事件总线位于Hub内部)相互通信。Node 通过事件总线向Hub 发送消息以启动注册过程。当Hub接收到消息时,通过HTTP与Node 联系以确认其存在。

要成功地将Node注册到Hub,必须公开Hub计算机上的事件总线端口(默认情况下为4442和4443)。这也适用于Node端口。有了它,Hub和Node都将能够通信。

如果Hub使用默认端口,则可以使用--hub标志注册Node

java -jar selenium-server-<version>.jar node --hub http://<hub-ip>:4444

当Hub不使用默认端口时,需要使用--publish-events和--subscribe-events标志。

例如,Hub使用9886、9887和9888端口

java -jar selenium-server-<version>.jar hub --publish-events tcp://<hub-ip>:9886 --subscribe-events tcp://<hub-ip>:9887 --port 9888

Node需要使用这些端口完成注册

java -jar selenium-server-<version>.jar node --publish-events tcp://<hub-ip>:9886 --subscribe-events tcp://<hub-ip>:9887

PS:Hub和Node的IP一定要一致,127.0.0.1 不能更换成本机IP,否则Node无法注册成功

3.Distributed(分发模式)

PS:这种模式比较麻烦,大家先了解一下即可
当使用分发模式Grid时,每个组件分别启动,并且理想情况下在不同的机器上启动。
PS:为了允许所有组件之间的流畅通信,正确地公开所有端口非常重要。
1)Event Bus事件总线:支持不同Grid组件之间的内部通信。
默认端口为:4442、4443、5557。

java -jar selenium-server-<version>.jar event-bus --publish-events tcp://<event-bus-ip>:4442 --subscribe-events tcp://<event-bus-ip>:4443 --port 5557

2)New Session Queue新建会话队列:将新的会话请求添加到队列中,该队列将由分发服务器查询
默认端口号为5559。

java -jar selenium-server-<version>.jar sessionqueue --port 5559

3)Session Map会话映射:将会话id映射到运行会话的Node
默认Session Map端口为5556。Session Map与事件总线(Event Bus)交互。

java -jar selenium-server-<version>.jar sessions --publish-events tcp://<event-bus-ip>:4442 --subscribe-events tcp://<event-bus-ip>:4443 --port 5556

4)Distributor分发器:查询新会话队列(New Session Queue)中的新会话请求,并在能力匹配时将其分配给节点(Node)。节点(Node)注册到分发服务器(Distributor)的方式与注册到中心/节点(Hub/Node)grid中的中心(Hub)的方式相同。
默认分发服务器(Distributor)端口为5553。分发服务器(Distributor)与新会话队列(New Session Queue)、会话映射(Session Map)、事件总线(Event Bus)和节点(Node)交互。

java -jar selenium-server-<version>.jar distributor --publish-events tcp://<event-bus-ip>:4442 --subscribe-events tcp://<event-bus-ip>:4443 --sessions http://<sessions-ip>:5556 --sessionqueue http://<new-session-queue-ip>:5559 --port 5553 --bind-bus false
  1. Router路由器:将新的会话请求重定向到队列,并将正在运行的会话请求重定向到运行该会话的节点(Node)。

默认路由器(Router)端口为4444。路由器(Router)与新建会话队列(New Session Queue)、会话映射(Session Map)和分发服务器(Distributor)交互。

java -jar selenium-server-<version>.jar router --sessions http://<sessions-ip>:5556 --distributor http://<distributor-ip>:5553 --sessionqueue http://<new-session-queue-ip>:5559 --port 4444
  1. Node(s)节点
    默认Node端口是5555
java -jar selenium-server-<version>.jar node --publish-events tcp://<event-bus-ip>:4442 --subscribe-events tcp://<event-bus-ip>:4443

三、什么时候应该使用Grid

在不同的浏览器类型、浏览器版本和操作系统上并行运行测试

减少执行测试套件所需的时间

Selenium Grid在多台机器(称为节点Nodes)上并行运行测试套件。对于大型且长时间运行的测试套件,这可以节省几分钟、几小时甚至几天的时间。这缩短了测试应用程序(AUT)更改时测试结果的周转时间。

Grid可以在多个不同的浏览器上(并行地)运行测试,也可以在同一浏览器的多个实例上运行。作为一个例子,让我们想象一个有六个节点(Nodes)的Grid。第一台机器是最新版本的Firefox,第二台是“最新减一”版本的Firefox,第三台是最新的Chrome,剩下的三台机器是Mac mini,它允许在最新版本的Safari上并行运行三个测试。

执行时间可以用一个简单的公式表示:

测试数*平均测试时间/节点数=总执行时间
15 * 45s / 1 = 11m 15s // Without Grid
15 * 45s / 5 = 2m 15s // Grid with 5 Nodes
15 * 45s / 15 = 45s // Grid with 15 Nodes
100 * 120s / 15 = 13m 20s // Would take over 3 hours without Grid

当测试套件正在执行时,Grid会按照测试中配置的方式分配测试以在这些浏览器上运行。

这样的配置可以大大加快即使是最大的Selenium测试套件的执行时间。

Selenium Grid完全是Selenium项目的原生部分,由在核心Selenium开发中工作的同一组提交者并行维护。由于认识到测试执行速度的重要性,Grid从早期开始就是Selenium项目的关键部分。

四、服务Grid的组件

Selenium Grid 4是基于以前版本的基础重写。除了对性能和标准遵从性的全面改进之外,Grid 的不同功能被打破,以贴合当下的计算和软件开发时代的需求。为了集装箱化和云分布式可伸缩性而专门构建的Selenium Grid 4是一个全新的现代解决方案。

路由器Router

路由器Router是网格Grid的入口点,接收所有外部请求,并将它们转发给正确的组件。

如果路由器收到一个新的会话请求,它将被转发到新会话队列New Session Queue。

如果请求属于一个已经存在的会话,路由器将查询会话映射Session Map来获得会话所在的节点Node ID,然后请求将直接转发给节点Node 。

路由器通过将请求发送到能够更好地处理请求的组件来平衡网格中的负载,而不会使流程中不需要的任何组件过载。

分发器Distributor

分发器有2个主要功能:

1)注册并跟踪所有节点及其功能

一个节点Node 通过事件总线Event Bus发送一个节点Node注册事件来注册到分发服务器Distributor 。分发服务器Distributor 读取它,然后尝试通过HTTP到达节点Node 以确认它的存在。如果请求成功,分发服务器Distributor 将注册节点并通过GridModel跟踪所有节点Node 的功能。

2)查询新会话队列并处理任何挂起的新会话请求

当一个新的会话请求被发送到路由器Router时,它会被转发到新会话队列New Session Queue,在那里它将在队列中等待。分发服务器Distributor 将轮询新会话队列中等待的新会话请求,然后找到可以在其中创建会话的合适节点Node 。创建会话之后,分发服务器Distributor 将session id和正在执行会话的节点Node 之间的关系存储在会话映射中。

会话映射Session Map

会话映射Session Map是一个数据存储,它保存会话id和运行会话的节点Node之间的关系。它支持路由器Router在转发请求到节点Node的过程中。路由器Router 将向会话映射 Session Map请求与会话id相关联的节点Node。

新会话队列New Session Queue

新会话队列以FIFO顺序保存所有新会话请求。它具有用于设置请求超时和请求重试间隔(检查超时的频率)的可配置参数。

路由器将新的会话请求添加到新会话队列中,并等待响应。新建会话队列定期检查队列中是否有请求超时,如果超时则拒绝请求并立即删除。

分发服务器定期检查插槽是否可用。如果是,分发服务器将在新会话队列中轮询第一个匹配请求。然后分发服务器尝试创建一个新的会话。

一旦请求的功能与任何空闲节点槽位的功能相匹配,分发服务器就会尝试获得可用的槽位。如果所有槽位都忙,分发服务器将把请求发送回队列。如果请求在重试或添加到队列前面时超时,将会被拒绝。

成功创建会话后,分发服务器将会话信息发送到新会话队列,然后将新会话队列发送回路由器,最后发送到客户机。

节点Node

一个网格Grid可以包含多个节点。每个Node管理运行它的机器上可用浏览器的插槽。

节点通过事件总线将自己注册到分发服务器,它的配置作为注册消息的一部分发送。

默认情况下,Node自动注册运行它的机器路径上可用的所有浏览器驱动程序。它还为基于铬的浏览器和Firefox在每个可用CPU上创建一个插槽。对于Safari,只创建一个插槽。通过特定的配置,它可以在Docker容器或中继命令中运行会话。

Node只执行接收到的命令,它不计算、做出判断或控制命令和响应流以外的任何东西。运行Node的机器不需要具有与其他组件相同的操作系统。例如,Windows节点可以在Edge上提供IE模式作为浏览器选项,而这在Linux或Mac上是不可能的,网格可以有多个配置了Windows、Mac或Linux的节点。

事件总线Event Bus

事件总线充当节点、分发服务器、新会话队列和会话映射之间的通信路径。Grid通过消息进行大部分内部通信,避免了昂贵的HTTP调用。当以完全分布式模式启动网格时,事件总线是应该启动的第一个组件。

五、配置

1. 配置帮助

获取有关配置网格的所有可用选项的信息.
ps:Help命令显示基于当前代码实现的信息. 因此, 如果文档没有更新, 它将提供准确的信息. 这是了解任何新版本Grid4配置的最便捷方法.

1.1 信息命令

Info命令提供以下主题的详细文档:
配置Selenium
安全
会话表配置
追踪

1.1.1 配置帮助

通过运行以下命令快速获取配置帮助:

java -jar selenium-server-<version>.jar info config

1.1.2 安全

获取构建网格服务器的详细信息, 用于安全通信和节点注册.

java -jar selenium-server-<version>.jar info security

1.1.3 会话表配置

默认情况下, 网格使用本地会话表来存储会话信息. 网格支持额外的存储选项, 比如Redis和JDBC-SQL支持的数据库. 要设置不同的会话存储, 请使用以下命令获取设置步骤:

java -jar selenium-server-<version>.jar info sessionmap

1.1.4 基于OpenTelemetry和Jaeger的追踪配置

默认情况下, 追踪是启用的. 要通过Jaeger导出追踪并将其可视化, 请使用以下命令进行说明:

java -jar selenium-server-<version>.jar info tracing

1.2 列出Selenium Grid的命令

java -jar selenium-server-<version>.jar --config-help

上述命令将显示所有可用的命令及其描述

1.3 组件帮助命令

在Selenium后面键入–help的配置选项, 以获取特定组件的配置信息
Standalone

java -jar selenium-server-<version>.jar standalone --help

Hub

java -jar selenium-server-<version>.jar hub --help

Sessions

java -jar selenium-server-<version>.jar sessions --help

队列器

java -jar selenium-server-<version>.jar sessionqueue --help

Distributor

java -jar selenium-server-<version>.jar distributor --help

Router

java -jar selenium-server-<version>.jar router --help

Node

java -jar selenium-server-<version>.jar node --help

2. CLI选项(命令行选项)

所有Grid组件配置CLI选项的详细信息.
可以使用不同的部分来配置Grid。每个部分都有可以通过命令行参数配置的选项。

下面是组件到组件映射的完整描述。

详细命令见官网链接:
https://www.selenium.dev/zh-cn/documentation/grid/configuration/cli_options/

2.1 配置示例

在启动Grid组件时,可以使用上面提到的所有选项。它们是探索Grid选项和尝试值以找到合适配置的好方法。
PS:我们建议使用Toml文件来配置Grid。配置文件提高了可读性,您还可以在源代码控制中检查它们。

在需要时,您可以将Toml文件配置与CLI参数结合起来
Command-line flags命令行标记
要将配置选项作为命令行标志传递,请标识组件的有效选项并遵循下面的模板。

java -jar selenium-server-<version>.jar <component> --<option> value


Standalone, setting max sessions and main port
单机模式,设置最大会话和主端口

java -jar selenium-server-<version>.jar standalone --max-sessions 4 --port 4444

Hub, setting a new session request timeout, a main port, and disabling tracing
中心,设置新的会话请求超时、主端口和禁用跟踪

java -jar selenium-server-<version>.jar hub --session-request-timeout 500 --port 3333 --tracing false

Node, with 4 max sessions, with debug(fine) log, 7777 as port, and only with Firefox and Edge
节点,有4个最大会话,调试(良好)日志,7777作为端口,只支持Firefox和Edge

java -jar selenium-server-<version>.jar node --max-sessions 4 --log-level "fine" --port 7777 --driver-implementation "firefox" --driver-implementation "edge"

Distributor, setting Session Map server url, Session Queue server url, and disabling bus
分发服务器、设置会话映射服务器url、会话队列服务器url和禁用总线

java -jar selenium-server-<version>.jar distributor --sessions http://localhost:5556 --sessionqueue http://localhost:5559 --bind-bus false

Setting custom capabilities for matching specific Nodes
设置用于匹配特定节点的自定义功能

重点:需要在所有节点的配置中设置自定义功能。它们还需要始终包含在每个会话请求中

Start the Hub

java -jar selenium-server-<version>.jar hub

Start the Node A with custom cap set to true
启动节点A,将自定义上限设置为true

java -jar selenium-server-<version>.jar node --detect-drivers false --driver-configuration display-name="Chrome (custom capability true)" max-sessions=1 stereotype='{"browserName":"chrome","gsg:customcap":true}' --port 6161

Start the Node B with custom cap set to false
启动节点B,并将自定义上限设置为false

java -jar selenium-server-<version>.jar node --detect-drivers false --driver-configuration display-name="Chrome (custom capability true)" max-sessions=1 stereotype='{"browserName":"chrome","gsg:customcap":false}' --port 6262

通过代码实现上述配置:

实现 Node A 的配置

from selenium import webdriver

chrome_options = webdriver.ChromeOptions()
chrome_options.set_capability("gsg:customcap", True)
driver = webdriver.Remote(
    command_executor='http://127.0.0.1:4444',
    options=chrome_options
)
driver.get("https://www.selenium.dev/")
driver.quit()

将自定义能力设置为false,实现节点B的配置

from selenium import webdriver

chrome_options = webdriver.ChromeOptions()
chrome_options.set_capability("gsg:customcap", False)
driver = webdriver.Remote(
    command_executor='http://127.0.0.1:4444',
    options=chrome_options
)
driver.get("https://www.selenium.dev/")
driver.quit()

3. Toml配置选项

使用Toml文件的Grid配置示例.
CLI选项 中 显示的所有选项都可以通过 TOML 文件进行配置. 此页面显示不同Grid组件的配置示例.

概述
Selenium Grid对配置文件使用 TOML 格式. 配置文件由多个部分组成, 每个部分都有选项及其各自的值.
有关详细的使用指南, 请参阅TOML文档 . 如果出现解析错误, 请使用 TOML linter 验证配置.

[section1]
option1="value"

[section2]
option2=["value1","value2"]
option3=true

下面是一些使用Toml文件配置的 Grid组件示例, 该组件可以 从下面的方式开始:

java -jar selenium-server-<version>.jar <component> --config /path/to/file/<file-name>.toml

单机模式
单机服务器, 在端口4449上运行, 新会话请求超时500秒.

[server]
port = 4449

[sessionqueue]
session-request-timeout = 500

特定浏览器和最大会话数限制
默认情况下仅启用Firefox 和Chrome的单机服务器或节点.

[node]
drivers = ["chrome", "firefox"]
max-sessions = 3

配置和定制驱动程序
具有定制驱动程序的单机或节点服务器, 允许使用Firefox试用或者每日构建的功能, 并且有不同的浏览器版本.

[node]
detect-drivers = false
[[node.driver-configuration]]
max-sessions = 100
display-name = "Firefox Nightly"
stereotype = "{\"browserName\": \"firefox\", \"browserVersion\": \"93\", \"platformName\": \"MAC\", \"moz:firefoxOptions\": {\"binary\": \"/Applications/Firefox Nightly.app/Contents/MacOS/firefox-bin\"}}"
[[node.driver-configuration]]
display-name = "Chrome Beta"
stereotype = "{\"browserName\": \"chrome\", \"browserVersion\": \"94\", \"platformName\": \"MAC\", \"goog:chromeOptions\": {\"binary\": \"/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta\"}}"
[[node.driver-configuration]]
display-name = "Chrome Dev"
stereotype = "{\"browserName\": \"chrome\", \"browserVersion\": \"95\", \"platformName\": \"MAC\", \"goog:chromeOptions\": {\"binary\": \"/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev\"}}"
webdriver-executable = '/path/to/chromedriver/95/chromedriver'

带Docker的单机或节点
单机或节点服务器能够在Docker容器中运行每个新会话. 禁用驱动程序检测, 则最多有2个并发会话. 原型配置需要映射一个Docker映像, Docker的守护进程需要通过http/tcp公开. 此外,可以通过 devices 属性定义在主机上可访问的哪些设备文件将在容器中可用。 有关 docker 设备映射如何工作的更多信息,请参阅 docker 文档

[node]
detect-drivers = false
max-sessions = 2

[docker]
configs = [
    "selenium/standalone-chrome:93.0", "{\"browserName\": \"chrome\", \"browserVersion\": \"91\"}", 
    "selenium/standalone-firefox:92.0", "{\"browserName\": \"firefox\", \"browserVersion\": \"92\"}"
]
#Optionally define all device files that should be mapped to docker containers
#devices = [
#    "/dev/kvm:/dev/kvm"
#]
url = "http://localhost:2375"
video-image = "selenium/video:latest"

将命令中继到支持WebDriver的服务端点
连接到支持WebDriver外部服务 的Selenium Grid非常有用. 这种服务的一个例子可以是 云提供商或Appium服务器. 这样, Grid可以实现对本地不存在的平台和版本的更多覆盖.
下面是一个将Appium服务器连接到Grid的示例.

[node]
detect-drivers = false

[relay]
# Default Appium/Cloud server endpoint
url = "http://localhost:4723/wd/hub"
status-endpoint = "/status"
# Stereotypes supported by the service. The initial number is "max-sessions", and will allocate 
# that many test slots to that particular configuration
configs = [
  "5", "{\"browserName\": \"chrome\", \"platformName\": \"android\", \"appium:platformVersion\": \"11\"}"
]

启用基本身份验证
通过配置包含用户名和密码的 路由器/中心和节点/单机的方式, 可以使用这样的基本身份验证保护Grid. 加载Grid UI或者开始一个新的会话时 需要此用户/密码组合.

[router]
username = "admin"
password = "myStrongPassword"

下面是一个代码示例, 演示如何使用配置的用户和密码启动会话.

from selenium import webdriver

gridUrl = "http://admin:myStrongPassword@localhost:4444"
chrome_options = webdriver.ChromeOptions()
driver = webdriver.Remote(
    command_executor=gridUrl,
    options=chrome_options
)
driver.get("https://www.selenium.dev/")
driver.quit()

设置用于匹配特定节点的自定义功能
重要:需要在所有节点的配置中设置自定义功能。它们还需要始终包含在每个会话请求中。

[node]
detect-drivers = false

[[node.driver-configuration]]
display-name = "chrome"
stereotype = '{"browserName": "chrome", "platformName": "macOS", "browserVersion":"96", "networkname:applicationName":"node_1", "nodename:applicationName":"app_1" }'
max-sessions = 5

下面是一个代码示例,演示如何实现上述配置

from selenium import webdriver

chrome_options = webdriver.ChromeOptions()
chrome_options.set_capability("networkname:applicationName", "node_1")
chrome_options.set_capability("nodename:applicationName", "app_1")
chrome_options.browser_version("96")
chrome_options.platform_name("macOS")
driver = webdriver.Remote(
    command_executor='http://127.0.0.1:4444',
    options=chrome_options
)
driver.get("https://www.selenium.dev/")
driver.quit()

posted on 2022-10-24 16:14  测试老宅男扶摇  阅读(557)  评论(0编辑  收藏  举报