# 追踪与调试 > **使用场景**:调试失败的操作、分析性能瓶颈、捕获执行证据、理解交互未生效的原因,或在自动化过程中检查网络及控制台活动。 > **前置条件**:[core-commands.md](core-commands.md) —— 掌握基本 CLI 用法 ## 快速参考 ```bash # 追踪会话 playwright-cli tracing-start playwright-cli open https://example.com playwright-cli click e4 playwright-cli fill e7 "test" playwright-cli tracing-stop # 查看控制台消息 playwright-cli console # 所有级别 playwright-cli console error # 仅错误 playwright-cli console warning # 仅警告 # 查看网络活动 playwright-cli network ``` ## 追踪 追踪会捕获**一切** —— 包括 DOM 快照、截图、网络活动、控制台日志以及时间信息,覆盖会话中的每一个操作。 ### 基本用法 ```bash # 在要调试的流程之前开始录制 playwright-cli tracing-start # 执行操作 playwright-cli open https://example.com playwright-cli snapshot playwright-cli click e4 playwright-cli fill e7 "test data" playwright-cli click e9 # 停止并保存追踪 playwright-cli tracing-stop ``` ### 追踪捕获的内容 | 类别 | 详情 | | --------------- | ----------------------------------------------------------- | | **操作** | 每次点击、填写、悬停、键盘输入、导航 —— 附带时间信息 | | **DOM 快照** | 每个操作前后的完整 DOM 状态 | | **截图** | 每一步的视觉状态 | | **网络** | 所有 HTTP 请求、响应、请求头、响应体、时间信息 | | **控制台** | 所有 `console.log`、`console.warn`、`console.error` 消息 | | **时间信息** | 每个操作的具体耗时 | | **来源** | 每个操作由哪个命令触发 | ### 追踪输出文件 当追踪激活时,Playwright 会创建一个 `traces/` 目录: **`trace-{时间戳}.trace`** —— 主追踪文件,包含: - 附带 DOM 快照的操作日志 - 每一步的截图 - 时间信息 - 控制台消息 **`trace-{时间戳}.network`** —— 网络活动: - 所有 HTTP 请求与响应 - 请求/响应请求头与响应体 - DNS、连接、TLS、TTFB、下载时间 - 资源大小及失败的请求 **`resources/`** —— 用于追踪回放的缓存资源: - 图片、字体、样式表、脚本 - 用于离线回放的响应体 ### 查看追踪 在 Playwright 的 Trace Viewer 中打开追踪 —— 这是一个用于逐步调试的丰富 GUI: ```bash # 在 Trace Viewer Web 应用中打开追踪 npx playwright show-trace traces/trace-123456.trace # 或使用在线 Trace Viewer # 将追踪文件上传至:https://trace.playwright.dev ``` Trace Viewer 会显示: - **时间轴**:带截图的逐步操作 - **DOM 快照**:检查每一步中的元素(类似 DevTools) - **网络**:所有请求的水fall图 - **控制台**:带时间戳的日志消息 - **来源**:触发每个操作的代码 ## 控制台监控 查看页面的 JavaScript 控制台输出 —— 对捕获错误至关重要: ```bash # 显示所有控制台消息 playwright-cli console # 按严重级别筛选 playwright-cli console error # 仅错误 playwright-cli console warning # 仅警告 playwright-cli console info # 仅信息消息 playwright-cli console log # 仅日志消息 ``` ### 常见调试模式 ```bash playwright-cli open https://app.example.com playwright-cli snapshot playwright-cli click e5 # 发生了意外情况 # 检查是否有 JavaScript 错误 playwright-cli console error # 输出可能显示: # [error] TypeError: Cannot read properties of undefined (reading 'map') # [error] Uncaught ReferenceError: processData is not defined ``` ### 交互期间查看控制台 使用 `run-code` 设置持续的控制台监控: ```bash playwright-cli run-code "async page => { page.on('console', msg => { if (msg.type() === 'error' || msg.type() === 'warning') { console.log(\`[\${msg.type()}] \${msg.text()}\`); } }); }" # 现在开始交互 —— 错误和警告会实时打印 playwright-cli click e5 playwright-cli fill e3 "test" ``` ### 捕获未捕获的异常 ```bash playwright-cli run-code "async page => { page.on('pageerror', error => { console.log('Uncaught exception:', error.message); }); }" ``` ## 网络监控 查看页面发出的所有网络请求: ```bash playwright-cli network ``` ### 实时查看网络 ```bash playwright-cli run-code "async page => { page.on('request', request => { console.log(\`>> \${request.method()} \${request.url()}\`); }); page.on('response', response => { console.log(\`<< \${response.status()} \${response.url()}\`); }); }" # 现在开始交互 —— 请求会实时打印 playwright-cli click e5 ``` ### 监控失败的请求 ```bash playwright-cli run-code "async page => { page.on('requestfailed', request => { console.log(\`FAILED: \${request.method()} \${request.url()} - \${request.failure()?.errorText}\`); }); }" ``` ### 检查特定响应 ```bash playwright-cli run-code "async page => { const response = await page.waitForResponse('**/api/users'); return { status: response.status(), statusText: response.statusText(), headers: response.headers(), body: await response.json() }; }" ``` ## 调试策略 ### 策略 1:快照前后对比 最简单的调试方法 —— 查看发生了什么变化: ```bash playwright-cli snapshot --filename=before.yaml playwright-cli click e5 playwright-cli snapshot --filename=after.yaml # 比较两个快照,了解变化内容 ``` ### 策略 2:追踪失败流程 在失败步骤之前开始追踪: ```bash playwright-cli tracing-start # 重现问题 playwright-cli goto https://app.example.com/checkout playwright-cli fill e1 "Jane Doe" playwright-cli click e5 # 此步骤失败 playwright-cli tracing-stop # 打开追踪,查看尝试点击时的 DOM 状态 ``` ### 策略 3:检查元素状态 当交互失败时,检查元素的实际状态: ```bash # 元素是否可见? playwright-cli eval "el => window.getComputedStyle(el).display" e5 playwright-cli eval "el => window.getComputedStyle(el).visibility" e5 playwright-cli eval "el => el.getBoundingClientRect()" e5 # 是否被其他元素遮挡? playwright-cli eval "el => { const rect = el.getBoundingClientRect(); const topEl = document.elementFromPoint(rect.x + rect.width/2, rect.y + rect.height/2); return topEl === el ? 'Element is on top' : 'Covered by: ' + topEl?.tagName + '.' + topEl?.className; }" e5 # 是否被禁用? playwright-cli eval "el => el.disabled" e5 playwright-cli eval "el => el.getAttribute('aria-disabled')" e5 ``` ### 策略 4:控制台 + 网络组合 ```bash # 同时监控控制台和网络 playwright-cli run-code "async page => { page.on('console', msg => { if (msg.type() === 'error') console.log('[CONSOLE]', msg.text()); }); page.on('requestfailed', req => { console.log('[NETWORK]', req.method(), req.url(), req.failure()?.errorText); }); page.on('response', resp => { if (resp.status() >= 400) { console.log('[HTTP ERROR]', resp.status(), resp.url()); } }); }" # 现在开始交互并查看错误 playwright-cli click e5 playwright-cli fill e3 "test" ``` ### 策略 5:等待与重试 如果操作因时序问题失败,可添加显式等待: ```bash # 等待元素变为可操作状态 playwright-cli run-code "async page => { await page.locator('#dynamic-button').waitFor({ state: 'visible', timeout: 10000 }); }" playwright-cli snapshot playwright-cli click e5 # 等待页面稳定 playwright-cli run-code "async page => { await page.waitForLoadState('networkidle'); }" playwright-cli snapshot ``` ## 性能分析 ### 测量页面加载时间 ```bash playwright-cli run-code "async page => { const timing = await page.evaluate(() => { const t = performance.timing; return { dns: t.domainLookupEnd - t.domainLookupStart, tcp: t.connectEnd - t.connectStart, ttfb: t.responseStart - t.requestStart, download: t.responseEnd - t.responseStart, domParsing: t.domInteractive - t.domLoading, domComplete: t.domComplete - t.domLoading, total: t.loadEventEnd - t.navigationStart }; }); return timing; }" ``` ### 使用 Navigation Timing API 分析 ```bash playwright-cli run-code "async page => { const entries = await page.evaluate(() => { return performance.getEntriesByType('navigation').map(e => ({ type: e.type, redirectTime: e.redirectEnd - e.redirectStart, dnsTime: e.domainLookupEnd - e.domainLookupStart, connectTime: e.connectEnd - e.connectStart, tlsTime: e.secureConnectionStart > 0 ? e.connectEnd - e.secureConnectionStart : 0, requestTime: e.responseStart - e.requestStart, responseTime: e.responseEnd - e.responseStart, domProcessing: e.domComplete - e.domInteractive, loadTime: e.loadEventEnd - e.loadEventStart, totalTime: e.loadEventEnd - e.startTime })); }); return entries; }" ``` ### 列出慢资源 ```bash playwright-cli run-code "async page => { const resources = await page.evaluate(() => { return performance.getEntriesByType('resource') .map(r => ({ name: r.name.split('/').pop(), duration: Math.round(r.duration), size: r.transferSize })) .sort((a, b) => b.duration - a.duration) .slice(0, 10); }); return resources; }" ``` ## 追踪 vs 视频 vs 截图 选择合适的捕获方式: | 功能 | 追踪 | 视频 | 截图 | | -------------------- | ------------ | ------------------- | -------------- | | **格式** | `.trace` 文件 | `.webm` 视频 | `.png` 图片 | | **DOM 检查** | 是 | 否 | 否 | | **网络详情** | 是 | 否 | 否 | | **逐步回放** | 是 | 连续播放 | 单帧 | | **控制台日志** | 是 | 否 | 否 | | **文件大小** | 中等 | 大 | 小 | | **最佳用途** | 调试 | 演示、文档 | 快速捕获 | ### 选择指南 - **操作失败且不明原因** → 追踪 - **需要向他人展示流程** → 视频 - **需要验证视觉状态** → 截图 - **需要分析性能** → 追踪(包含网络水fall图) - **CI 中失败测试的产物** → 追踪 + 截图 ## 最佳实践 ### 1. 在问题发生前开始追踪 追踪导致失败的整个流程,而不仅仅是失败的步骤: ```bash playwright-cli tracing-start # 从头重现完整流程 playwright-cli open https://app.example.com playwright-cli fill e1 "user@example.com" playwright-cli click e3 # ... 直至失败的所有步骤 ... playwright-cli tracing-stop ``` ### 2. 主动使用控制台监控 在任何调试会话开始时即启动控制台监控: ```bash playwright-cli run-code "async page => { page.on('console', msg => console.log(\`[\${msg.type()}] \${msg.text()}\`)); page.on('pageerror', err => console.log('[EXCEPTION]', err.message)); }" ``` ### 3. 清理旧追踪 追踪文件会占用大量磁盘空间: ```bash # 删除 7 天前的追踪文件 find .playwright-cli/traces -mtime +7 -delete ``` ### 4. 组合多种技术 最有效的调试往往结合多种方法: ```bash playwright-cli tracing-start # 捕获一切 playwright-cli console error # 监控 JS 错误 playwright-cli network # 监控失败的请求 playwright-cli snapshot # 查看当前状态 # ... 交互并调试 ... playwright-cli tracing-stop # 保存追踪用于详细分析 ```