Selenium 4新特性深度解析 – Relative Locator与W3C协议实战

---

前言

大家好,我是测开老王。做自动化测试7年,Selenium用了5年多,见证了它从2.x到4.x的演变。今天这篇,我想系统聊聊Selenium 4的新特性,以及在实际项目中的应用。 Selenium 4在2021年底正式发布,相比3.x版本,变化很大: 这些变化对我们写自动化脚本有什么影响?下面一一分析。 ---

一、W3C协议:告别JSON Wire Protocol

什么是W3C协议?

在Selenium 3时代,WebDriver使用的是JSON Wire Protocol,这是Selenium自定义的协议。不同浏览器厂商需要实现自己的Driver(如chromedriver、geckodriver),协议实现有差异,导致一些兼容性问题。 Selenium 4采用了W3C WebDriver标准协议,这意味着:

对我们有什么影响?

好消息:现有脚本基本不用改。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、没有稳定的class,XPath又很长很脆弱,怎么办?

Relative Locator登场

Relative Locator允许我们根据元素之间的空间关系来定位:

实战示例

假设有一个登录表单: `html Logo ` 输入框没有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. 动态内容页面 - 列表项没有固定属性 - 但相对位置关系稳定

注意事项

---

三、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会: ---

四、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完全重构了架构:

新架构组件

启动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兼容性很好。 ---

参考资料

--- 下期预告:Playwright vs Cypress对决 - 2026年最值得学习的自动化测试框架
分享到:

探索 RunnerGo 全栈测试平台

RunnerGo 是一款面向企业的全栈测试平台,集接口测试、自动化测试、性能测试、UI测试于一体,助力企业提升研发效能。

接口测试
性能测试
自动化测试
UI测试
免费体验 RunnerGo