做过UI自动化测试的同学,大概率都有过这样的崩溃时刻:
明明手动操作一遍就能成功的场景,写成自动化脚本就频繁报错;元素定位明明没错,却总出现“元素不可见”“超时加载”;想模拟浏览器的特殊操作(比如清除缓存、模拟网络异常),翻遍资料也找不到简洁的实现方式;跨浏览器兼容测试更是麻烦,每个浏览器都要单独调试,耗时又费力。
UI测试本身就繁琐,再加上这些“卡脖子”问题,不仅拖慢测试进度,还会让测试效率大打折扣——很多时候,我们不是在写脚本,就是在调试脚本的路上。
其实不用这么内耗,今天给大家分享UI测试必备的两个Agent Skill技能:chrome-cdp 和 playwright-cli,能很好的解决上述这些痛点,让我们可以把更多精力放在核心测试场景上。
无论是新手入门,还是老测试优化工作流,掌握这两个技能,都能让你的UI测试效率翻倍,下面就来拆解一下。
一、先说说:当前UI测试的核心痛点
在介绍这两个skill之前,我们得先梳理清楚当前UI测试的核心痛点有哪些,因为只有知道问题在哪,才能明白这两个技能的价值所在,看看你日常工作中是不是也经常遇到这些情况:
- 元素定位难,脚本稳定性差:传统UI自动化依赖元素定位工具(如selenium、playwright),但遇到动态元素、隐藏元素、iframe嵌套,就容易定位失败;甚至浏览器渲染延迟,都会导致脚本报错,调试成本极高。
- 浏览器操作受限,场景覆盖不全:想模拟浏览器的高级操作(如模拟网络卡顿、清除localStorage、截图录屏、模拟手机端适配),传统工具要么实现复杂,要么根本不支持,导致很多边缘场景无法覆盖。
- 跨浏览器兼容测试繁琐:不同浏览器(Chrome、Firefox、Edge)的内核不同,脚本在一个浏览器能跑通,在另一个浏览器就报错,需要单独适配,重复工作量大。
- 脚本编写效率低,上手门槛高:传统自动化脚本需要手动编写大量代码,新手入门慢;而且脚本复用性差,换一个测试场景,就要重新编写或大幅修改。
- 调试不便,问题定位难:脚本报错后,只能一步步打印日志排查,无法直观看到浏览器的运行状态,很难快速定位是元素问题、环境问题,还是脚本逻辑问题。
这些痛点,本质上是“工具适配性不足”和“操作复杂度高”导致的。
而chrome-cdp和playwright-cli,正是针对性解决这些问题的两个测试“神器”——一个专注于Chrome浏览器的深度操控,一个专注于跨浏览器的高效自动化,两者搭配,几乎能覆盖所有UI测试场景。
两个工具的项目地址放在文章末尾,文章较长,建议先点赞收藏,慢慢看
二、chrome-cdp: Chrome浏览器的“底层操控神器”
1. 什么是chrome-cdp?
chrome-cdp 全称 Chrome DevTools Protocol(Chrome开发者工具协议),简单来说,它是Chrome浏览器提供的一套“底层接口”,允许我们通过代码(或命令)直接操控Chrome浏览器的所有行为——包括页面渲染、网络请求、元素操作、调试日志等,相当于直接“接管”Chrome的核心功能。
它不是一个独立工具,而是Chrome内置的协议,我们可以通过Python、JavaScript等语言调用它的接口,实现传统UI测试工具做不到的高级操作。很多知名测试工具(如Playwright、Puppeteer),底层其实都依赖了chrome-cdp。
2. 能解决哪些UI测试痛点?
chrome-cdp 最核心的价值,是“突破传统工具的限制”,可以解决以下几个核心痛点:
- 解决“元素定位不稳定”:直接通过浏览器底层接口获取元素,不受动态渲染、隐藏元素影响,定位成功率大幅提升;
- 解决“浏览器高级操作难”:轻松实现模拟网络异常(断网、卡顿)、清除缓存/本地存储、截图录屏、模拟手机端设备等操作;
- 解决“调试不便”:可实时获取浏览器的运行日志、网络请求详情,报错后能快速定位问题根源,不用再盲目排查。
3. 基础用法(新手友好,快速上手)
chrome-cdp 的用法有两种:一种是通过命令行直接调用(适合快速调试),另一种是通过代码调用(适合集成到自动化脚本)。
3.1 命令行用法(快速调试)
首先,确保你的Chrome浏览器已安装,然后打开命令行,输入以下命令,启动Chrome并开启CDP协议:
# Windows
chrome.exe --remote-debugging-port=9222 --user-data-dir=c:/chrome_data
# Mac/Linux
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome_data
# Linux服务器无头模式
google-chrome-stable --headless=new --remote-debugging-port=9222 --no-sandbox
说明:
- --remote-debugging-port=9222:指定调试端口为9222,后续通过这个端口连接Chrome;
- --user-data-dir:指定Chrome的用户数据目录,避免影响本地正常使用的Chrome配置。
--headless=new:新版无头模式(支持完整功能)
启动后,打开浏览器访问 http://localhost:9222,就能看到当前Chrome的所有标签页,点击任意标签页,即可进入CDP调试界面,可直接查看网络请求、元素信息、执行JS命令等。
3.2 集成到自动化脚本
场景1:性能指标自动化采集
使用CDP采集Web性能数据,替代手动F12操作
class PerformanceTester:
def __init__(self, cdp: CDPController):
self.cdp = cdp
def measure_page_load(self, url: str):
"""测量页面加载性能"""
# 启用性能监控
self.cdp.send("Performance.enable")
self.cdp.send("Network.enable")
# 清除缓存(模拟首次访问)
self.cdp.send("Network.clearBrowserCache")
# 记录开始时间
start_time = time.time()
# 导航到页面
self.cdp.send("Page.navigate", {"url": url})
self.cdp.wait_event("Page.loadEventFired", timeout_s=30)
# 获取Performance API数据
timing_result = self.cdp.eval("""
JSON.stringify(performance.timing)
""")
timing = json.loads(timing_result)
# 计算关键指标
navigation_start = timing["navigationStart"]
metrics = {
"DNS查询": timing["domainLookupEnd"] - timing["domainLookupStart"],
"TCP连接": timing["connectEnd"] - timing["connectStart"],
"首字节时间(TTFB)": timing["responseStart"] - navigation_start,
"DOM解析": timing["domContentLoadedEventEnd"] - timing["domInteractive"],
"完整加载": timing["loadEventEnd"] - navigation_start,
"总耗时": time.time() - start_time
}
# 获取资源加载详情
entries_result = self.cdp.eval("""
JSON.stringify(performance.getEntriesByType('resource').map(r => ({
name: r.name,
duration: r.duration,
size: r.transferSize
})))
""")
resources = json.loads(entries_result)
return {
"页面": url,
"指标(ms)": metrics,
"资源数": len(resources),
"慢资源": [r for r in resources if r["duration"] > 1000][:5] # Top5慢资源
}
# 批量性能测试
def test_batch_performance(urls: list):
cdp = CDPController(ws_url)
tester = PerformanceTester(cdp)
results = []
for url in urls:
result = tester.measure_page_load(url)
results.append(result)
print(f"📊 {url}: 加载耗时 {result['指标(ms)']['完整加载']}ms")
# 生成性能报告
with open("performance_report.json", "w") as f:
json.dump(results, f, indent=2, ensure_ascii=False)
return results
场景2:与Selenium 4集成(增强现有框架)
Selenium 4原生支持CDP,可以无缝集成
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
# 启动浏览器
driver = webdriver.Chrome(service=Service("./chromedriver"))
# 获取CDP会话
dev_tools = driver.devtools
# 创建CDP会话
dev_tools.create_session()
# ===== 示例1:模拟地理位置 =====
def test_geo_location():
# 设置地理位置为上海
driver.execute_cdp_cmd("Emulation.setGeolocationOverride", {
"latitude": 31.2304,
"longitude": 121.4737,
"accuracy": 100
})
driver.get("https://map.baidu.com")
# 验证地图是否定位到上海
# ===== 示例2:模拟弱网环境 =====
def test_slow_network():
# 启用网络监控
dev_tools.send(dev_tools.network.enable())
# 模拟3G网络
driver.execute_cdp_cmd("Network.emulateNetworkConditions", {
"offline": False,
"latency": 200, # 200ms延迟
"downloadThroughput": 780 * 1024 / 8, # 780 Kbps
"uploadThroughput": 330 * 1024 / 8 # 330 Kbps
})
driver.get("https://your-app.com")
# 测试在弱网下的加载表现
# ===== 示例3:拦截并修改请求 =====
def test_request_interception():
# 启用Fetch域
driver.execute_cdp_cmd("Fetch.enable", {
"patterns": [{"urlPattern": "*api*", "requestStage": "Request"}]
})
# 添加监听器(需要通过WebSocket或Selenium的EventListener)
driver.get("https://your-app.com")
# 验证特定API请求是否携带了正确参数
# ===== 示例4:性能指标采集 =====
def test_performance_metrics():
# 启用性能监控
driver.execute_cdp_cmd("Performance.enable")
driver.get("https://your-app.com")
# 获取性能指标
metrics = driver.execute_cdp_cmd("Performance.getMetrics", {})
print("性能指标:", metrics)
# 获取页面加载时间
timing = driver.execute_script("""
return JSON.stringify(performance.timing)
""")
场景3:与Playwright集成(深度控制)
Playwright底层基于CDP,可以直接访问原始CDP会话
from playwright.sync_api import sync_playwright
def test_with_cdp_session():
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context()
page = context.new_page()
# 创建CDP会话(直接访问Chrome DevTools Protocol)
cdp_session = context.new_cdp_session(page)
# ===== 高级网络控制 =====
# 启用网络监控
cdp_session.send("Network.enable")
# 模拟特定网络条件
cdp_session.send("Network.emulateNetworkConditions", {
"offline": False,
"downloadThroughput": 1.5 * 1024 * 1024 / 8, # 1.5 Mbps
"uploadThroughput": 750 * 1024 / 8, # 750 Kbps
"latency": 150 # 150ms延迟
})
# ===== 性能监控 =====
cdp_session.send("Performance.enable")
page.goto("https://example.com")
# 获取性能指标
metrics = cdp_session.send("Performance.getMetrics")
print("Chrome性能指标:", metrics)
# ===== 模拟设备 =====
cdp_session.send("Emulation.setDeviceMetricsOverride", {
"width": 390,
"height": 844,
"deviceScaleFactor": 3,
"mobile": True,
"screenOrientation": {"angle": 0, "type": "portraitPrimary"}
})
# 截图验证移动端渲染
page.screenshot(path="mobile_view.png", full_page=True)
browser.close()
场景4:视觉回归测试(结合截图对比)
class VisualRegressionTester:
def __init__(self, cdp: CDPController):
self.cdp = cdp
self.baseline_dir = "./visual_baselines"
self.current_dir = "./visual_current"
def capture_full_page(self, name: str):
"""捕获完整页面截图(包含视口外内容)"""
# 获取页面完整尺寸
metrics = self.cdp.send("Page.getLayoutMetrics")
content_width = metrics["contentSize"]["width"]
content_height = metrics["contentSize"]["height"]
# 设置视口为页面完整尺寸
self.cdp.send("Emulation.setDeviceMetricsOverride", {
"width": content_width,
"height": content_height,
"deviceScaleFactor": 1,
"mobile": False
})
# 截图
self.cdp.screenshot(f"{self.current_dir}/{name}.png")
# 恢复默认视口
self.cdp.send("Emulation.clearDeviceMetricsOverride")
def compare_with_baseline(self, name: str):
"""对比当前截图与基线"""
from PIL import Image
import pixelmatch
baseline = Image.open(f"{self.baseline_dir}/{name}.png")
current = Image.open(f"{self.current_dir}/{name}.png")
diff = pixelmatch(baseline, current, threshold=0.1)
if diff > 100: # 差异像素数阈值
raise AssertionError(f"❌ 视觉回归测试失败: {name}, 差异像素: {diff}")
print(f"✅ 视觉测试通过: {name}")
# 使用示例
def test_ui_regression():
cdp = CDPController(ws_url)
tester = VisualRegressionTester(cdp)
# 测试关键页面
pages = [
("首页", "https://app.com/home"),
("商品详情", "https://app.com/product/123"),
("购物车", "https://app.com/cart")
]
for name, url in pages:
cdp.send("Page.navigate", {"url": url})
cdp.wait_event("Page.loadEventFired")
time.sleep(2) # 等待动画完成
tester.capture_full_page(name)
tester.compare_with_baseline(name)
4. 在UI自动化测试中的应用场景
chrome-cdp 通常更适合“Chrome浏览器专属场景”的自动化,尤其是需要高级操作的场景,比如:
- 异常场景测试:模拟网络断连、网络延迟、弱网环境,测试页面的异常提示和恢复机制;
- 缓存相关测试:清除localStorage、sessionStorage,测试页面的缓存逻辑是否正常;
- 截图录屏自动化:测试过程中自动截图、录屏,用于测试报告留存或问题复现;
- 复杂元素操作:处理iframe嵌套、动态加载元素,避免传统定位工具的报错问题;
- 调试优化:实时获取浏览器日志、网络请求,快速定位自动化脚本的报错原因。
三、playwright-cli: 跨浏览器UI自动化“神器”
1. 什么是playwright-cli?
playwright-cli 是 Microsoft 推出的 Playwright 自动化测试工具的命令行版本,Playwright 本身是一个跨浏览器自动化工具,支持Chrome、Firefox、Edge、Safari等所有主流浏览器,而playwright-cli 则是它的“命令行简化版”——无需编写复杂代码,通过命令就能快速实现UI自动化,同时也支持代码集成,兼顾新手友好和实用性。
它的核心优势是“跨浏览器兼容”和“脚本自动生成”,能大幅降低UI自动化的上手门槛,提升脚本编写效率,解决传统自动化工具“跨浏览器适配难”的痛点。
2. 能解决哪些UI测试痛点?
如果说chrome-cdp 专注于Chrome的深度操控,那么playwright-cli 就是“全能型选手”。
它重点解决了以下几个痛点:
- 解决“跨浏览器兼容测试繁琐”:一套脚本,可直接运行在Chrome、Firefox、Edge等所有主流浏览器,无需单独适配;
- 解决“脚本编写效率低”:支持“录制脚本”,手动操作一遍,自动生成自动化脚本,新手也能快速上手;
- 解决“元素定位难”:内置强大的元素定位引擎,自动识别动态元素、隐藏元素,无需手动编写定位表达式;
- 解决“脚本稳定性差”:自动等待页面加载、元素渲染,避免因渲染延迟导致的报错,脚本成功率极高。
3. 在UI自动化测试中的应用场景
playwright-cli 适合“全场景、跨浏览器”的UI自动化,尤其是需要规模化、高效执行的场景,比如:
- 跨浏览器兼容测试:一套脚本,批量运行在所有主流浏览器,快速排查浏览器兼容问题;
- 常规UI自动化脚本编写:通过录制功能,快速生成脚本,减少手动编码工作量,适合新手或高频场景;
- 回归测试:将常用测试场景录制为脚本,每次版本更新后,一键运行,快速完成回归测试;
- 多环境测试:支持指定环境(开发、测试、生产),一键切换,无需修改脚本;
- 并行测试:支持多浏览器、多用例并行执行,大幅缩短测试时间,提升测试效率。
4. 基础用法(新手友好,3步上手)
playwright-cli 的用法非常简单,核心分为“安装→录制→运行”三步,全程无需复杂配置,新手也能快速上手。
# 1. 安装Playwright CLI
npm install -g @playwright/cli@latest
npx playwright install # 安装浏览器
# 2. 体验UI模式(强烈推荐)
npx playwright test --ui
# 3. 录制你的第一个测试
npx playwright codegen https://testfather.cn
常用命令一览:
| 命令 | 功能 |
|---|---|
npx playwright test | 运行所有测试 |
npx playwright test --ui | UI模式交互式运行 |
npx playwright codegen | 录制生成测试代码 |
npx playwright show-trace | 查看测试追踪 |
npx playwright test --debug | 调试模式运行 |
问题1:调试困难
传统方式:测试挂了,看日志猜原因,复现靠运气。
解决方案:
- Playwright CLI的UI模式:每一步操作都有前后截图,鼠标悬停就能看到DOM状态变化
- CDP的Debugger Domain:可以在特定代码行设置断点,精确控制执行流程
# 开启UI模式,像看视频一样看测试执行
npx playwright test --ui
问题2:元素定位不稳定
传统方式:Thread.sleep(3000)硬等,或者XPath一写就失效。
解决方案:
- Playwright的自动等待:内置智能等待机制,元素可操作时才执行
- CDP的DOM查询:通过Runtime.evaluate直接执行JS获取元素,绕过复杂的Selector
# Playwright CLI直接执行JS获取元素
playwright-cli eval "document.querySelector('#app').innerText"
问题3:多浏览器兼容性
传统方式:Chrome一套、Firefox一套、Safari又一套。
解决方案:
- Playwright CLI的Project配置:一份配置,指定Chromium/Firefox/WebKit
- CDP的通用性:Edge、Opera等Chromium内核浏览器都支持CDP
# 同时跑三个浏览器
npx playwright test --project=chromium --project=firefox --project=webkit
问题4:性能测试工具割裂
传统方式:Lighthouse、PageSpeed、WebPageTest来回切换。
解决方案:
- CDP的Performance Domain:浏览器原生指标采集,直接获取Chrome性能时间线、内存堆快照
- Playwright的Tracing:自动生成性能追踪文件,可视化分析
# 生成性能追踪文件
npx playwright test --trace=on
npx playwright show-trace trace.zip
5. 实战用法
场景1:快速验证页面功能(零代码)
需求:测试登录流程是否正常,不写一行代码。
# 1. 录制操作生成代码
npx playwright codegen https://your-app.com/login
# 2. 直接在命令行执行测试
npx playwright test --headed --grep "login"
效果:Playwright自动打开浏览器,执行操作,生成可复用的测试脚本。
场景2:AI驱动的智能测试(自然语言转自动化)
需求:用自然语言描述,让AI自动执行测试。
结合Playwright CLI与AI Skills
# 用户输入:"打开百度,搜索'UI自动化',截图保存"
# AI自动生成并执行:
playwright-cli open https://www.baidu.com
playwright-cli type "#kw" "UI自动化"
playwright-cli click "#su"
playwright-cli screenshot --full-page
核心价值:测试人员用自然语言描述场景,AI自动转换为可执行命令
场景3:深度网络层测试(CDP高级用法)
需求:验证前端错误监控是否上报,拦截并分析上报请求。
// 通过CDP监听网络请求
const CDP = require('chrome-remote-interface');
async function testErrorReporting() {
const client = await CDP();
const { Network, Page } = client;
// 开启网络监控
await Network.enable();
// 拦截所有请求
Network.requestWillBeSent((params) => {
if (params.request.url.includes('error-report')) {
console.log('✅ 错误上报请求已捕获:', params.request);
}
});
// 导航到测试页面
await Page.navigate({ url: 'https://your-app.com' });
}
效果:可以验证错误监控、性能上报、埋点数据等前端"黑盒"行为。
场景4:移动端适配测试(视口模拟)
需求:测试页面在不同手机上的显示效果。
# Playwright CLI调整视口模拟iPhone
playwright-cli resize 375 667 # iPhone SE尺寸
playwright-cli screenshot --full-page mobile-view.png
# 或者使用内置设备配置
npx playwright test --project="Mobile Safari"
场景5:CI/CD集成(无头模式+报告)
需求:在Jenkins/GitHub Actions中自动运行测试。
# 无头模式运行,生成HTML报告
npx playwright test --reporter=html
# 查看报告
npx playwright show-report
# 多Worker并行,提速
npx playwright test --workers=4
四、实战建议:两个Skills搭配使用
chrome-cdp 和 playwright-cli 不是对立的,而是互补的——将两者搭配使用,chrome-cdp给了你浏览器底层的"上帝视角",playwright-cli给了你高效便捷的"操作界面"。两者结合,既能应对复杂的底层协议操作,又能享受现代自动化工具的便捷性。
能覆盖几乎所有UI测试场景,实现效率最大化,给大家一个实战搭配建议:
- 常规自动化场景:用 playwright-cli 录制脚本,实现跨浏览器兼容测试、常规回归测试,快速生成脚本,减少编码工作量;
- Chrome专属高级场景:用 chrome-cdp 补充高级操作,比如模拟网络异常、清除缓存、复杂元素调试等,解决playwright-cli 无法实现的细节场景;
- 脚本优化:用 playwright-cli 生成基础脚本,再用 chrome-cdp 的接口优化脚本细节(如提升定位稳定性、添加异常处理),让脚本更健壮;
- 调试排错:遇到脚本报错,先用 chrome-cdp 查看浏览器底层日志、网络请求,快速定位问题根源,再用playwright-cli 调整脚本。
五、新手入门建议
UI自动化测试的终极形态,不是写更多的代码,而是让工具理解你的意图。
chrome-cdp和playwright-cli,一个代表深度,一个代表广度。装上它们,你会发现:原来UI测试可以这么丝滑。
| 名称 | 项目地址 |
|---|---|
| chrome-cdp | github.com/pasky/chrom… |
| playwright-cli | github.com/microsoft/p… |
如果是UI测试新手,建议先从 playwright-cli 入手——它的录制功能能让你快速上手,感受到自动化测试的便捷,建立信心;等熟悉了基础操作后,再学习 chrome-cdp,补充高级操作能力,两者结合,就能轻松应对所有UI测试场景。
如果是有一定经验的测试同学,建议直接掌握两者的搭配用法——用playwright-cli 提升效率,用chrome-cdp 解决难点,能大幅优化你的工作流,摆脱重复劳动,把精力放在更有价值的测试设计上。
UI测试的核心是“高效、稳定、全面”,而chrome-cdp 和 playwright-cli,正是帮你实现这一目标的两个关键技能。赶紧动手尝试起来,相信你会发现,UI测试其实可以很轻松~
更多、更详细、全面的AI测试、AI编程、AI技能进阶系统化实战教程,欢迎加入:「狂师. AI进化社」一起探讨学习!