Selenium Grid | 菜鸟教程,先学习前面这篇文章里面的基础,再看我下面写的文章会更加容易理解。
一、Selenium Grid 是什么?
1. 核心概念
Selenium Grid 是一个代理服务器,它允许你将测试命令路由到多个远程浏览器实例。它的主要目的是:
-
并行执行:同时在多个浏览器和操作系统上运行测试
-
跨浏览器测试:在不同的浏览器类型和版本上测试应用
-
跨平台测试:在不同的操作系统上测试应用
-
负载分发:将测试负载分发到多台机器
2. 架构组件
Selenium Grid 4 采用新的架构,包含两个主要组件:
-
Hub:中心节点,接收测试请求并分发到合适的节点
-
Node:工作节点,执行实际的测试命令
python
[你的测试脚本] → [Hub] → [Node 1 (Chrome on Windows)]
│
→ [Node 2 (Firefox on macOS)]
│
→ [Node 3 (Safari on iOS)]
二、Selenium Grid 4 的部署方式
1. 独立模式 (Standalone) - 最简单的方式
独立模式将 Hub 和 Node 合并到一个进程中,适合快速开始:
bash
# 下载最新版本的Selenium Server
# 从 https://www.selenium.dev/downloads/ 下载selenium-server-x.x.x.jar
# 启动Standalone模式
java -jar selenium-server-4.15.0.jar standalone
# 指定端口
java -jar selenium-server-4.15.0.jar standalone --port 4444
2. 中心与节点模式 (Hub and Nodes) - 经典分布式模式
启动 Hub:
bash
# 启动Hub(默认端口4444)
java -jar selenium-server-4.15.0.jar hub
# 自定义配置启动Hub
java -jar selenium-server-4.15.0.jar hub \
--port 4444 \
--selenium-manager true \
--cors true
启动 Node:
bash
# 注册Node到Hub
java -jar selenium-server-4.15.0.jar node \
--hub http://localhost:4444
# 指定Node配置
java -jar selenium-server-4.15.0.jar node \
--hub http://localhost:4444 \
--port 5555 \
--max-sessions 5 \
--browser browserName=chrome,maxInstances=5
3. 分布式模式 - 高级部署
对于大规模部署,可以使用完全分布式的模式:
bash
# 启动Event Bus(事件总线)
java -jar selenium-server-4.15.0.jar event-bus
# 启动Session Map(会话映射)
java -jar selenium-server-4.15.0.jar sessions
# 启动Session Queue(会话队列)
java -jar selenium-server-4.15.0.jar sessionqueue
# 启动Distributor(分发器)
java -jar selenium-server-4.15.0.jar distributor
# 启动Router(路由器)
java -jar selenium-server-4.15.0.jar router
# 启动Node(节点)
java -jar selenium-server-4.15.0.jar node
三、Docker 部署 - 推荐的生产环境方式
使用 Docker 可以简化 Grid 的部署和管理:
1. 快速启动 Standalone
bash
docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-chrome:4.15.0
2. 启动完整的 Hub + Node 集群
bash
# 启动Hub
docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:4.15.0
# 启动Chrome节点
docker run -d --name selenium-chrome-node \
-p 5900:5900 \
-e SE_EVENT_BUS_HOST=selenium-hub \
-e SE_EVENT_BUS_PUBLISH_PORT=4442 \
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \
-v /dev/shm:/dev/shm \
selenium/node-chrome:4.15.0
# 启动Firefox节点
docker run -d --name selenium-firefox-node \
-p 5901:5900 \
-e SE_EVENT_BUS_HOST=selenium-hub \
-e SE_EVENT_BUS_PUBLISH_PORT=4442 \
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \
-v /dev/shm:/dev/shm \
selenium/node-firefox:4.15.0
3. 使用 Docker Compose(推荐)
创建 docker-compose.yml
文件:
bash
version: '3.8'
services:
hub:
image: selenium/hub:4.15.0
container_name: selenium-hub
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
chrome:
image: selenium/node-chrome:4.15.0
container_name: selenium-chrome
shm_size: 2gb
environment:
- SE_EVENT_BUS_HOST=hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
depends_on:
- hub
firefox:
image: selenium/node-firefox:4.15.0
container_name: selenium-firefox
shm_size: 2gb
environment:
- SE_EVENT_BUS_HOST=hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
depends_on:
- hub
然后运行:
bash
docker-compose up -d
四、编写兼容 Grid 的测试脚本
1. 基本 Grid 测试脚本
python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.remote.webdriver import WebDriver
def test_with_grid():
# Grid Hub 的地址
grid_url = "http://localhost:4444"
# 创建浏览器选项
chrome_options = Options()
chrome_options.set_capability("browserName", "chrome")
chrome_options.set_capability("browserVersion", "latest")
chrome_options.set_capability("platformName", "LINUX")
# 创建远程WebDriver实例
driver = webdriver.Remote(
command_executor=grid_url,
options=chrome_options
)
try:
# 执行测试
driver.get("https://www.example.com")
print(f"页面标题: {driver.title}")
# 进行一些操作
search_box = driver.find_element(By.NAME, "q")
search_box.send_keys("Selenium Grid")
search_box.submit()
# 验证结果
assert "Selenium Grid" in driver.title
finally:
# 关闭浏览器
driver.quit()
if __name__ == "__main__":
test_with_grid()
2. 多浏览器并行测试
python
import concurrent.futures
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
def run_test(browser_name, browser_version="latest"):
grid_url = "http://localhost:4444"
if browser_name.lower() == "chrome":
options = ChromeOptions()
elif browser_name.lower() == "firefox":
options = FirefoxOptions()
else:
raise ValueError(f"不支持的浏览器: {browser_name}")
options.set_capability("browserName", browser_name)
options.set_capability("browserVersion", browser_version)
options.set_capability("platformName", "LINUX")
driver = webdriver.Remote(
command_executor=grid_url,
options=options
)
try:
driver.get("https://www.example.com")
print(f"{browser_name}: 页面标题 - {driver.title}")
# 执行一些测试逻辑
# ...
return f"{browser_name} 测试通过"
finally:
driver.quit()
# 并行运行多个浏览器测试
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
browsers = ["chrome", "firefox", "chrome"]
results = list(executor.map(run_test, browsers))
for result in results:
print(result)
3. 高级配置和自定义能力
python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def test_with_advanced_capabilities():
grid_url = "http://localhost:4444"
chrome_options = Options()
# 设置基本能力
chrome_options.set_capability("browserName", "chrome")
chrome_options.set_capability("browserVersion", "118")
chrome_options.set_capability("platformName", "Windows 10")
# 设置高级能力
chrome_options.set_capability("selenoid:options", {
"enableVNC": True, # 启用VNC远程查看
"enableVideo": False, # 禁用视频录制
"enableLog": True, # 启用日志记录
"screenResolution": "1920x1080x24",
"env": ["LANG=zh_CN.UTF-8", "LANGUAGE=zh:en", "LC_ALL=zh_CN.UTF-8"],
"timeZone": "Asia/Shanghai"
})
# 添加自定义标签,用于筛选节点
chrome_options.set_capability("custom:label", "smoke-test")
driver = webdriver.Remote(
command_executor=grid_url,
options=chrome_options
)
try:
driver.get("https://www.example.com")
# 测试逻辑...
finally:
driver.quit()
五、Grid 管理和监控
1. Grid 控制台
访问 http://localhost:4444
查看 Grid 控制台,可以:
-
查看所有注册的节点
-
监控当前会话
-
查看节点配置和能力
2. 使用 Grid API
Grid 提供了 REST API 用于管理和监控:
python
import requests
import json
class GridManager:
def __init__(self, grid_url="http://localhost:4444"):
self.grid_url = grid_url
def get_grid_status(self):
"""获取Grid状态"""
response = requests.get(f"{self.grid_url}/status")
return response.json()
def get_nodes_info(self):
"""获取所有节点信息"""
response = requests.get(f"{self.grid_url}/graphql", json={
"query": "query { nodes { id, uri, status, slots { id, session { id } } } }"
})
return response.json()
def terminate_session(self, session_id):
"""终止指定会话"""
response = requests.delete(f"{self.grid_url}/se/grid/session/{session_id}")
return response.status_code == 200
# 使用示例
grid_manager = GridManager()
status = grid_manager.get_grid_status()
print(json.dumps(status, indent=2))
3. 实时监控和日志
python
# 查看Grid日志(如果使用Docker)
docker logs -f selenium-hub
# 查看特定节点日志
docker logs -f selenium-chrome-node
六、最佳实践和故障排除
1. 最佳实践
-
使用适当的等待策略:Grid 环境中的网络延迟可能更高
-
实现重试机制:处理偶尔的网络问题
-
合理配置节点 :根据硬件资源设置
max-sessions
-
使用标签筛选:为节点添加标签,用于定向测试
-
监控资源使用:避免节点过载
2. 常见问题解决
问题:无法连接到 Hub
python
# 添加连接超时和重试
from urllib3.exceptions import MaxRetryError
try:
driver = webdriver.Remote(
command_executor=grid_url,
options=options,
command_timeout=300 # 5分钟超时
)
except MaxRetryError:
print("无法连接到Grid Hub,请检查Hub是否运行")
问题:节点注册失败
python
# 检查防火墙设置
# 确保Hub和Node之间的网络连通性
# 检查端口是否开放
问题:会话创建超时
python
# 增加节点启动参数中的超时时间
java -jar selenium-server.jar node --session-timeout 600
3. 性能优化建议
python
# 为每个节点分配适当的内存
java -jar selenium-server.jar node -Xmx4g
# 限制每个节点的最大会话数
java -jar selenium-server.jar node --max-sessions 5
# 使用更快的浏览器驱动
# 考虑使用chromedriver的--no-sandbox选项
七、高级特性
1. 自定义节点配置
创建 config.toml
配置文件:
python
[node]
detect-drivers = false
max-sessions = 5
session-timeout = 300
[[node.driver-config]]
display-name = "Chrome"
stereotype = '{"browserName": "chrome", "browserVersion": "118", "platformName": "Linux"}'
max-sessions = 2
[[node.driver-config]]
display-name = "Firefox"
stereotype = '{"browserName": "firefox", "browserVersion": "118", "platformName": "Linux"}'
max-sessions = 2
然后使用配置文件启动:
bash
java -jar selenium-server.jar node --config config.toml
2. 负载均衡和高可用
部署多个 Hub 实现高可用:
bash
# 启动多个Hub实例
java -jar selenium-server.jar hub --port 4444
java -jar selenium-server.jar hub --port 4445
# 使用负载均衡器(如Nginx)分发请求
Selenium Grid 是构建大规模自动化测试基础设施的核心组件。通过合理配置和使用,你可以显著提升测试效率和覆盖率。记得根据实际需求选择合适的部署模式,并始终监控 Grid 的健康状态。