测试开发 | 跨平台设备管理方案 Selenium Grid

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

Selenium Grid 是 Selenium 的三大组件之一它可以在多台机器上并行运行测试集中管理不同的浏览器版本和浏览器配置。通过将客户端命令发送到远程浏览器的实例, Selenium Grid 允许在远程计算机 (虚拟或真实) 上执行 WebDriver 脚本. 它旨在提供一种在多台计算机上并行运行测试的简便方法。

官方文档https://www.selenium.dev/

使用场景

场景一 实现分布式执行测试提高执行效率

比如我们有 1000 条用例执行如果在本机执行一条用例耗时 100 秒,执行完成则需要大约 27 小时 1000*100/60/60=27个小时。如果让这些用例并发执行比如分配 6 台计算机每个计算机执行 1000/6 大约 166 条用例那时间大约节省了 6 倍原来需要大约 27 个小时现在可能只需要 4.5 个小时左右就基本完成了 分布式并发执行可以让我们用例的执行总时长指数级的缩小从而效率得到很大的提升。

场景二 解决浏览器兼容性问题

比如还是 1000 条用例需要分别在 Chrome、Firefox、Edge、Safari 这些浏览器上都执行一遍保证每个浏览器上都能正常执行测试浏览器的兼容性。这时也可以使用 Selenium Grid通过 Selenium Grid 将这些请求分发到不同的系统、不同浏览器中执行。这些浏览器可以分别布署在不同的计算机中比如可以布署在 Linux 、Windows、Mac 上都可以作为它的 Node 结点从而解决兼容性测试的问题

新特性

Selenium Grid 4 是一个全新的工具它能够支持完全分布式的测试。Selenium Grid4 也兼容了之前 Selenium Grid3 的工作模式在 Selenium Grid3 的基础上又添加了一些新的通讯方式使它通讯速度更快。另外现在很多公司都支持容器化部署Selenium Grid 4 也提供了的 Docker 支持。相比 Selenium Grid 3Selenium Grid 4 更容易在虚拟机上使用。

Selenium Grid4 有三个新特性

  • 特性一Hub 和 Node 使用同一个 jar 服务。

  • 特性二架构优化在 Selenium Grid 4 版本的全新架构中划分成了组件Router、Distributor、Node、Session Map、Session Queue、Event Bus。

  • 特性三支持不同的运行模式Selenium 4 支持三种网格类型包括 Standalone Mode 独立模式、Classical Grid 经典网格模式、Fully Distributed 完全分布式

原理分析

下面这张图是官方提供的 Selenium Grid4 的工作原理图

image1080×646 59.2 KB

从图中可以看到 Selenium Grid 包括六大组件分别是

  • Router 路由器

  • Distributor 分发服务器

  • Session Map 会话映射

  • Node 测试节点

  • New Session Queue 新的会话队列

  • Event Bus 事件总线

下面分别说一下这六个组件所负责的职责

  • Router 路由器Router 是所有组件的入口所有向服务器发送的外部请求第一个会经常 Router 组件。

  • Distributor 分发服务器它有两个主要的功能第一个功能注册并跟踪所有 Node 节点第二个功能就是查询新会话队列并处理挂起的新会话请求。当一个新的请求到达 Router 时它会被转发到 New Session Queue在队列中等待。分发服务器会轮询新会话队列查找挂起的新会话请求为这个请求找到匹配的节点之后会创建一个新的会话这个会话的 ID 以及 URI 会存储在 Session Map 中。

  • Session Map 会话映射它是一个数据存储区它存储了会话 ID 与对应的会话结点的关系在 Router 转发请求到对应的结点时要先在 Session Map 中查看对应的关系再进行请求。

  • Node 测试节点结点有多个每个结点管理多个可用的浏览器的插槽结点只负责执行命令不需要做出其它的判断。这个 Node 可以配置在 Windows、Mac、Linux 等任何系统上。

  • New Session Queue 新的会话队列从 Router 发过来的请求它会先放到这个队列中 等待被分发服务器分发出去这个队列有一些特殊的功能它能够定期的检查会话是否超时如果超时请求将被拒绝并立即删除。这里可以配置一些参数来处理超时时长等参数。

  • Event Bus 事件总线充当了节点、分发服务器、新会话队列和会话映射之间的通信路径使用了 socket 通信。在完全分布式模式下启动 selenium grid 时事件总线会是第一个被启动起来的组件。

环境安装

  • Java11 及以上版本。

  • 下载被测试的浏览器Chrome/Firefox/Edge/Safari 等。

  • 配置环境变量将对应的 driver 提前下载下来配置到环境变量中。或者将下载的 driver 放在与 selenium server 的 jar 包同级目录下也可以。

  • Selenium Server 下载建议使用 4.4.0 版本。

运行方式

单机运行 - 独立模式

1. 命令行启动 server

  1. 命令行 cd 到当前下载 jar 包的路径下

cd Desktop

  1. java -jar 启动对应的 jar 包java -jar selenium-server-<version>.jar standalone

java -jar selenium-server-4.4.0.jar standalone

启动成功后对应命令行显示Started Selenium Standalone ...如图

image1080×209 75.2 KB

  1. 查看 UI 界面 > 浏览器输入网址查看 UI 界面UI 链接

image1080×563 40.9 KB

  1. 查看 Grid status 状态 > 浏览器输入网址查看 status 状态Status 状态

image1080×1008 129 KB

2. 代码运行

直接运行代码发现在本地运行单线程只不过通过 Selenium Grid 来转发请求。

运行步骤
  1. SeleniumGrid 会创建一个 Queue 队列里面包含了启动的参数代码

image1080×261 7.31 KB

  1. SeleniumGrid 创建一个本地的 session然后再打开浏览器运行测试用例

image1080×288 32.6 KB

单浏览器运行代码

示例代码如下

"""

@Author: 霍格沃兹测试开发学社-西西

@Desc: '更多测试开发技术探讨请访问https://ceshiren.com/t/topic/15860'

"""from time import sleepfrom selenium import webdriverfrom selenium.webdriver.common.by import Byclass TestSingleNode:

def setup_method(self):

# 创建Options ,新版本DesireCapability已弃用

options = webdriver.EdgeOptions() # 通过URL和options 创建一个远程的连接

# client 发送请求要发送给selenium grid hub 结点 hub 结点会将请求分发到对应的node

self.driver = webdriver.Remote(

command_executor='http://10.1.1.104:4444',

options=options

) def test_singlenode1(self):

# 打开 baidu 页

self.driver.get("http://www.baidu.com") # 向输入框中输入

self.driver.find_element(By.ID, 'kw').send_keys("firefox") # 点击搜索框

self.driver.find_element(By.ID, 'su').click() # 等待一秒

sleep(1) # 断言输入内容在页面中

assert "firefox" in self.driver.page_source def teardown_method(self):

self.driver.quit()

多浏览器运行代码

创建测试文件 test_multi_node.py 示例代码如下

from time import sleepfrom selenium import webdriverfrom selenium.webdriver.common.by import Byclass TestMultiNode:

def setup_method(self):

options = webdriver.ChromeOptions()

self.driver = webdriver.Remote(

command_executor='http://10.1.1.104:4444',

options=options

) def test_multinode1(self):

# 打开 baidu 页

self.driver.get("http://www.baidu.com") # 向输入框中输入

self.driver.find_element(By.ID, 'kw').send_keys("selenium") # 点击搜索框

self.driver.find_element(By.ID, 'su').click() # 等待一秒

sleep(1) # 断言输入内容在页面中

assert "selenium" in self.driver.page_source def test_multinode2(self):

# 打开 baidu 页

self.driver.get("http://www.baidu.com") # 向输入框中输入

self.driver.find_element(By.ID, 'kw').send_keys("appium") # 点击搜索框

self.driver.find_element(By.ID, 'su').click() # 等待一秒

sleep(1) # 断言输入内容在页面中

assert "appium" in self.driver.page_source def test_multinode3(self):

# 打开 baidu 页

self.driver.get("http://www.baidu.com") # 向输入框中输入

self.driver.find_element(By.ID, 'kw').send_keys("pytest") # 点击搜索框

self.driver.find_element(By.ID, 'su').click() # 等待一秒

sleep(1) # 断言输入内容在页面中

assert "pytest" in self.driver.page_source def test_multinode4(self):

# 打开 baidu 页

self.driver.get("http://www.baidu.com") # 向输入框中输入

self.driver.find_element(By.ID, 'kw').send_keys("requests") # 点击搜索框

self.driver.find_element(By.ID, 'su').click() # 等待一秒

sleep(1) # 断言输入内容在页面中

assert "requests" in self.driver.page_source def test_multinode5(self):

# 打开 baidu 页

self.driver.get("http://www.baidu.com") # 向输入框中输入

self.driver.find_element(By.ID, 'kw').send_keys("java") # 点击搜索框

self.driver.find_element(By.ID, 'su').click() # 等待一秒

sleep(1) # 断言输入内容在页面中

assert "java" in self.driver.page_source def teardown_method(self):

self.driver.quit()

为了模拟多浏览器并发运行使用 pytest 的插件 pytest-xdist 实现分布式并发执行方式提前安装 pytest-xdist 插件然后使用命令执行用例。打开命令提示行或者终端使用cd 命令进入到文件所在路径然后执行 pytest test_multi_node.py -n 3 --alluredir ./results命令。执行完用例之后会把测试报告结果统一汇总到results 目录中。

单机运行 - 经典网格模式

1. 命令行启动 hub

  1. 命令行 cd 到当前下载 jar 包的路径下

cd Desktop

  1. java -jar 以 Hub 启动对应的 jar 包java -jar selenium-server-<version>.jar hub

java -jar selenium-server-4.4.0.jar hub

image1080×164 76.3 KB

此时启动了 Router,Distributor,Session Map,New Session Queue,Event Bus虽然已经有了对应集线器但是还没有 node 节点注册进来。
如果不把节点 Node 注册进来对应的集线器无法知道哪个物理机器可以被分发请求对应的 Router 就无法把测试用例进行分发。
  1. 查看状态的 UI 界面

image1080×338 69 KB

2. 命令行启动 node

  1. 同一机器上启动 nodejava -jar selenium-server-<version>.jar node --detect-drivers true

java -jar selenium-server-4.4.0.jar node --detect-drivers true

image1080×493 119 KB

此时 node 节点创建成功并且 hub 上注册对应 node 节点

image1080×308 115 KB

健康检测就是每隔 2 分钟会 ping 一下对应 URL 看看是否可以 ping 成功对应是否处于活动状态
  1. 再次查看状态的 UI 界面

image1080×610 67.4 KB

3. 代码运行

直接运行代码发现在本地运行单线程只不过通过 Selenium Grid 来转发请求。

多系统运行 - 分发模式

在经典网格模式等基础上再在其他机器上启动一个 node 角色。

1. 不同机器上启动 node

  1. 不同机器上启动 nodejava -jar selenium-server-<version>.jar node --detect-drivers true --publish-events tcp://<ip> --subscribe-events tcp://<ip>

java -jar selenium-server-4.4.0.jar node --detect-drivers true --publish-events tcp://10.1.1.178:4442 --subscribe-events tcp://10.1.1.178:4443

image1080×243 150 KB

此时 node 节点创建成功并且在远端 hub 上注册对应 node 节点
  1. 查看状态的 UI 界面

image1080×446 47.8 KB

注意

不同机器上启动的时候需要安装相同版本的 jar 及根据机器上的浏览器下载对应的 driver

2. 不同机器上运行用例

使用代码运行时会发现对应分发时会分给不同的系统运行代码如图

image1080×321 44.9 KB

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6