—
前言
大家好,我是测开老王。做自动化测试7年,Selenium用了5年多,见证了它从2.x到4.x的演变。今天这篇,我想系统聊聊Selenium 4的新特性,以及在实际项目中的应用。
Selenium 4在2021年底正式发布,相比3.x版本,变化很大:
- 完全支持W3C标准协议
- 全新的Relative Locator(相对定位器)
- 重构的Grid架构
- 更好的Chrome DevTools支持
- 窗口管理API增强
这些变化对我们写自动化脚本有什么影响?下面一一分析。
—
一、W3C协议:告别JSON Wire Protocol
什么是W3C协议?
在Selenium 3时代,WebDriver使用的是JSON Wire Protocol,这是Selenium自定义的协议。不同浏览器厂商需要实现自己的Driver(如chromedriver、geckodriver),协议实现有差异,导致一些兼容性问题。
Selenium 4采用了W3C WebDriver标准协议,这意味着:
- 浏览器Driver实现更统一
- API行为更一致
- 跨浏览器测试更稳定
对我们有什么影响?
好消息:现有脚本基本不用改。Selenium 4向后兼容,大部分API保持不变。
但有一些细节需要注意:
python
Selenium 3 的写法(仍然支持)
driver.find_element_by_id(“username”)
driver.find_element_by_css_selector(“.btn-primary”)
Selenium 4 推荐的写法
from selenium.webdriver.common.by import By
driver.find_element(By.ID, “username”)
driver.find_element(By.CSS_SELECTOR, “.btn-primary”)
旧方法会显示DeprecationWarning,建议统一改成新写法。
实际踩坑
我在升级一个老项目时,遇到一个问题:
python
这行代码在Selenium 3可以运行
element = driver.find_element_by_xpath(“//div[@class=’content’]”)
Selenium 4 会报警告
DeprecationWarning: find_element_by_* is deprecated. Please use find_element() instead
解决方案:写一个兼容层脚本,批量替换旧方法。
python
兼容层示例
def find_by_id(driver, element_id):
return driver.find_element(By.ID, element_id)
def find_by_xpath(driver, xpath):
return driver.find_element(By.XPATH, xpath)
—
二、Relative Locator:革命性的定位方式
这是Selenium 4最让人兴奋的新特性!
传统定位的痛点
以前定位元素,只能用:
- ID、Name、ClassName
- XPath、CSS Selector
- LinkText、PartialLinkText
但这些定位器都是基于元素自身的属性。如果元素没有ID、没有稳定的class,XPath又很长很脆弱,怎么办?
Relative Locator登场
Relative Locator允许我们根据元素之间的空间关系来定位:
above()– 在某元素上方below()– 在某元素下方toLeftOf()– 在某元素左侧toRightOf()– 在某元素右侧near()– 在某元素附近
实战示例
假设有一个登录表单:
html

输入框没有ID,class也是动态生成的。用传统方式定位很麻烦。
用Relative Locator:
python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
driver = webdriver.Chrome()
driver.get(“https://example.com/login”)
先定位Logo
logo = driver.find_element(By.TAG_NAME, “img”)
定位用户名输入框(在Logo下方)
username = driver.find_element(locate_with(By.TAG_NAME, “input”).below(logo))
定位密码输入框(在用户名下方)
password = driver.find_element(locate_with(By.TAG_NAME, “input”).below(username))
定位登录按钮(在密码下方)
login_btn = driver.find_element(locate_with(By.TAG_NAME, “button”).below(password))
组合使用
Relative Locator可以组合使用:
python
from selenium.webdriver.support.relative_locator import locate_with
定位在Logo下方、且在右侧栏内的元素
element = driver.find_element(
locate_with(By.TAG_NAME, “input”)
.below(logo)
.to_right_of(sidebar)
)
使用场景
Relative Locator特别适合这些场景:
1. 表单布局固定但元素属性不稳定
– 输入框没有固定ID
– 根据Label文本定位旁边输入框
2. 响应式布局测试
– 不同屏幕尺寸下元素位置变化
– 相对位置关系保持不变
3. 动态内容页面
– 列表项没有固定属性
– 但相对位置关系稳定
注意事项
- Relative Locator依赖元素在页面上的实际位置
- 元素不可见时定位会失败
- 复杂布局可能有歧义(比如多个元素都符合条件)
—
三、WebDriverManager自动管理Driver
Selenium 4不再内置Driver管理,推荐使用WebDriverManager。
以前的痛点
python
以前需要手动下载chromedriver,放到指定路径
driver = webdriver.Chrome(“/path/to/chromedriver”)
问题:
1. Chrome更新后,Driver版本不匹配
2. 不同环境路径不同
3. CI/CD环境配置麻烦
现在的解决方案
python
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
自动下载和管理Driver
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
WebDriverManager会:
- 自动检测浏览器版本
- 下载匹配的Driver
- 缓存到本地,不用重复下载
—
四、Chrome DevTools支持
Selenium 4可以直接调用Chrome DevTools协议,实现更强大的功能。
模拟网络条件
python
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = webdriver.Chrome()
启用网络模拟
driver.execute_cdp_cmd(“Network.enable”, {})
模拟3G网络
driver.execute_cdp_cmd(“Network.emulateNetworkConditions”, {
“offline”: False,
“latency”: 100, # 延迟100ms
“downloadThroughput”: 500 * 1024, # 下载速度 500KB/s
“uploadThroughput”: 500 * 1024, # 上传速度 500KB/s
})
driver.get(“https://example.com”)
模拟地理位置
python
模拟GPS位置
driver.execute_cdp_cmd(“Emulation.setGeolocationOverride”, {
“latitude”: 39.9042, # 北京
“longitude”: 116.4074,
“accuracy”: 100
})
driver.get(“https://example.com/map”)
截取特定元素
python
截取特定元素的截图
element = driver.find_element(By.ID, “chart”)
screenshot = element.screenshot_as_png
with open(“chart.png”, “wb”) as f:
f.write(screenshot)
—
五、窗口管理增强
Selenium 4新增了窗口管理API:
python
创建新标签页
driver.switch_to.new_window(“tab”)
创建新窗口
driver.switch_to.new_window(“window”)
获取窗口信息
window_rect = driver.get_window_rect()
print(window_rect) # {‘x’: 10, ‘y’: 10, ‘width’: 1200, ‘height’: 800}
设置窗口位置和大小
driver.set_window_rect(x=100, y=100, width=1024, height=768)
最小化窗口
driver.minimize_window()
全屏
driver.fullscreen_window()
—
六、Grid 4架构重构
Selenium Grid 4完全重构了架构:
新架构组件
- Router:接收请求,分发到对应组件
- Distributor:选择合适的Node执行测试
- Session Map:存储Session与Node的映射关系
- Session Queue:新Session请求队列
- Nodes:实际执行测试的节点
启动Standalone模式
bash
java -jar selenium-server-4.x.jar standalone
启动Hub-Node模式
bash
启动Hub
java -jar selenium-server-4.x.jar hub
启动Node(连接到Hub)
java -jar selenium-server-4.x.jar node –hub http://hub-ip:4444
Docker部署
bash
启动Standalone
docker run -d -p 4444:4444 selenium/standalone-chrome
启动Hub
docker run -d -p 4444:4444 selenium/hub
启动Node
docker run -d –net host selenium/node-chrome
—
七、实战:Selenium 4自动化框架模板
下面是一个基于Selenium 4 + Pytest的自动化框架示例:
python
conftest.py
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
@pytest.fixture(scope=”function”)
def driver():
“””初始化WebDriver”””
options = webdriver.ChromeOptions()
options.add_argument(“–headless”) # 无头模式
options.add_argument(“–no-sandbox”)
options.add_argument(“–disable-dev-shm-usage”)
driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=options
)
driver.maximize_window()
yield driver
driver.quit()
test_login.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
def test_login(driver):
“””测试登录功能”””
driver.get(“https://example.com/login”)
# 使用Relative Locator定位
logo = driver.find_element(By.TAG_NAME, “img”)
username = driver.find_element(locate_with(By.TAG_NAME, “input”).below(logo))
password = driver.find_element(locate_with(By.TAG_NAME, “input”).below(username))
username.send_keys(“testuser”)
password.send_keys(“password123”)
login_btn = driver.find_element(By.CSS_SELECTOR, “button[type=’submit’]”)
login_btn.click()
# 验证登录成功
assert “dashboard” in driver.current_url
—
八、升级建议
如果你的项目还在用Selenium 3,升级到4的建议:
1. 先升级依赖
bash
pip install selenium==4.x.x
pip install webdriver-manager
2. 更新定位器写法
– 全局搜索 find_element_by_
– 替换为 find_element(By.*, ...)
3. 测试Relative Locator
– 找几个复杂定位场景
– 尝试用Relative Locator简化
4. 评估Grid升级
– 如果用了Grid,评估是否升级到4.x
– Docker部署更简单
—
总结
Selenium 4是一次重要的版本升级,主要收益:
| 特性 | 收益 |
|---|---|
| W3C协议 | 跨浏览器兼容性更好 |
| Relative Locator | 定位元素更灵活 |
| DevTools支持 | 网络模拟、地理位置等高级功能 |
| Grid重构 | 分布式测试更易部署 |
| API现代化 | 代码更规范、可维护 |
对于新项目,建议直接用Selenium 4。老项目升级风险不大,API兼容性很好。
—
参考资料
- Selenium官方文档:https://www.selenium.dev/documentation/
- Selenium 4 Release Notes:https://github.com/SeleniumHQ/selenium/blob/trunk/java/CHANGELOG
- WebDriver W3C标准:https://w3c.github.io/webdriver/
- RunnerGo博客:https://www.runnergo.com/blog/
—
下期预告:Playwright vs Cypress对决 – 2026年最值得学习的自动化测试框架