1. 项目概述从“我截图了”到“这是证据”在浏览器测试、问题排查或者功能验收的日常工作中我们最常听到的一句话可能就是“我截图了你看这里有问题。”然后一张孤零零的截图被丢进聊天窗口附带着一句模糊的描述。几小时后当你想复现这个问题或者向团队其他成员解释时却发现信息严重缺失当时的具体操作步骤是什么网络请求正常吗控制台有没有报错除了这张图其他上下文全凭记忆。这就是browser-proof要解决的核心痛点。它不是一个全新的测试框架而是一个证据打包器。它的设计哲学非常直接将一次浏览器会话无论是手动探索、自动化测试还是问题复现中所有零散的“证据”——截图、操作步骤、预期结果、实际结果、控制台日志、网络请求快照——以一种机器可读且人类可读的结构化方式组织起来形成一个完整的“证据包”。想象一下你不再是提交一个模糊的“bug报告”而是提交一个完整的“案件卷宗”。这个卷宗里时间线清晰物证齐全任何接手的人都能根据它精确地还原现场。这对于跨团队协作、历史问题追溯、上线前的最终验证价值巨大。我把它用在我们团队的ClawHub自动化流程和手工QA验收中彻底改变了我们沟通和归档问题的方式。2. 核心设计思路构建可复现的证据链browser-proof的聪明之处在于它采用了“清单驱动”的模型。整个证据包的核心是一个JSON格式的清单文件Manifest它定义了会话的元信息并串联起所有步骤和证据。这种设计带来了几个关键优势2.1 结构化优于碎片化传统的证据收集是碎片化的截图放在一个文件夹步骤写在记事本日志另外保存。browser-proof强制你从一开始就进行结构化思考。一个会话Session对应一个明确的目标Goal比如“验证登录和支付流程”。这个会话下可以划分多个“界面”Surface例如“登录页”、“商品页”、“收银台”。每个界面下才是具体的操作步骤Step。这种结构天然契合现代Web应用多页面、多状态的特点。它让你在组织证据时逻辑非常清晰避免了把所有东西都堆在一起的混乱。2.2 机器可读与自动化友好JSON清单是机器可读的这意味着它可以被轻松地集成到CI/CD流水线中。例如一个Playwright自动化测试脚本在运行后可以调用browser-proof的脚本将测试步骤、通过/失败状态、以及每一步的截图自动追加到证据包中。最终生成的Markdown报告可以直接作为流水线的一个Artifact或者自动评论到对应的代码提交或工单里。这种自动化能力将测试证据从“事后手动整理”变成了“过程自动记录”极大地提升了效率和可靠性。2.3 证据的完整性校验这是我认为最实用的功能之一。browser-proof提供了一个check_browser_proof_bundle.py脚本。它会像一个严格的审计员检查你的证据包证据缺失某个步骤标记了需要截图但对应的图片文件不存在。路径问题清单中引用了绝对路径这会导致证据包无法在不同机器上共享。失败步骤无证据如果一个步骤的状态是“失败”或“阻塞”却没有附加任何控制台日志或网络错误等关键证据检查器会发出警告。这个检查步骤强制形成了良好的实践失败的用例必须有充分的“罪证”而不仅仅是标记一个红叉。3. 核心组件与实操详解browser-proof项目包含几个核心Python脚本每个都扮演着特定的角色。我们来逐一拆解它们的用法和背后的考量。3.1 初始化会话init_browser_proof_session.py这是创建证据包的起点。你需要定义整个调查或测试任务的框架。python3 skill/browser-proof/scripts/init_browser_proof_session.py \ --out /tmp/browser-proof.json \ --session-id “20240520-payment-fix-verification” \ --app “电商平台V2.1” \ --goal “验证修复后的信用卡支付流程在Chrome v123上的表现” \ --base-url https://staging.example.com \ --surface login \ --surface product-detail \ --surface checkout参数解析与经验之谈--session-id:建议使用具有唯一性和描述性的ID例如结合日期、功能名和版本。这方便后续搜索和归档。避免使用简单的test1。--app和--goal: 这里填写具体的应用名称和测试目标。目标写得越具体证据包的针对性就越强。例如不是“测试支付”而是“测试美国用户使用Visa卡进行3D Secure验证支付”。--base-url: 这是所有相对路径的基准。非常重要确保它与后续测试中使用的基准URL一致。--surface: 你可以一次定义多个界面。这步是在搭建证据包的“目录结构”。即使暂时用不到所有界面先定义出来也有助于保持结构完整。注意生成的browser-proof.json文件是后续所有操作的“总纲”。建议将其纳入版本控制如Git这样证据包的结构和历史变更也能被追踪。3.2 追加证据步骤append_browser_proof_step.py这是最常用的命令用于在会话中添加具体的操作和证据。每一步都像在填写一个标准的证据记录单。python3 skill/browser-proof/scripts/append_browser_proof_step.py \ --manifest /tmp/browser-proof.json \ --step-id “checkout-enter-card” \ --surface checkout \ --action “在支付表单中输入信用卡号 ‘4111 1111 1111 1111’ 有效期 ‘12/30’ CVV ‘123’” \ --expected “输入框成功接收输入无即时验证错误提示” \ --actual “信用卡号输入框触发了Luhn算法验证并显示成功图标” \ --status passed \ --screenshot “artifacts/checkout-card-input.png” \ --console “artifacts/checkout-console-log.json” \ --network “artifacts/checkout-network-requests.har”关键字段深度解读--action:描述要具体到可执行。不要写“测试支付”要写“点击‘信用卡支付’按钮选择‘Visa’在卡号栏输入…”。好的Action描述能让任何人直接照着重现。--expectedvs--actual: 这是证据链的逻辑核心。“预期”是你认为系统应该发生什么“实际”是你观察到的真实情况。两者的对比直接决定了--status。对于失败的步骤这里的差异描述就是根本原因分析的起点。--status: 通常为passed,failed,blocked。blocked很有用表示由于前置条件不满足如环境故障而无法继续区别于功能本身的失败。--screenshot/--console/--network:这些是引用不是数据本身。脚本不会自动帮你截图或抓日志它只是记录这些证据文件的路径。你需要用其他工具如Playwright、Puppeteer、浏览器开发者工具手动导出来生成这些文件并确保路径正确。实操心得证据文件的组织我强烈建议建立一个清晰的目录结构来存放证据文件例如/tmp/evidence-bundle/ ├── browser-proof.json # 清单文件 └── artifacts/ # 所有证据文件 ├── login-page.png ├── checkout-card-input.png ├── checkout-console-log.json └── checkout-network-requests.har在--screenshot参数中使用相对路径如artifacts/checkout-card-input.png这样整个evidence-bundle文件夹可以被打包压缩分享给任何人所有引用都不会失效。3.3 证据包完整性校验check_browser_proof_bundle.py在生成最终报告前或者将证据包提交给同事前运行一次检查是必不可少的良好习惯。python3 skill/browser-proof/scripts/check_browser_proof_bundle.py \ --manifest /tmp/browser-proof.json \ --repo-root /tmp/evidence-bundle \ --out /tmp/check-results.json--repo-root: 这个参数指定了证据文件存储的根目录。检查器会基于这个根目录去解析清单中记录的文件相对路径判断文件是否存在。输出是一个JSON文件会详细列出所有问题errors致命问题如文件缺失、warnings建议改进项如失败步骤缺少详细证据。一个真实的踩坑案例我曾有一次标记某个步骤为failed但只附了一张模糊的截图。检查器给出了警告“失败步骤 ‘api-call-500’ 缺少 console 或 network 证据”。我回头重新检查才发现需要打开浏览器开发者工具的“保存日志”功能复现后导出了完整的网络HAR文件里面清晰显示了一个500错误的API响应问题立刻定位到了后端接口。这个检查机制迫使你收集有效的、多维度的证据。3.4 生成可读报告render_browser_proof_report.py这是最后一步将结构化的JSON清单渲染成优雅的Markdown报告用于分享和呈现。python3 skill/browser-proof/scripts/render_browser_proof_report.py \ --manifest /tmp/browser-proof.json \ --out /tmp/browser-proof-report.md生成的Markdown报告结构清晰汇总了通过/失败/阻塞的统计并按照Surface和Step ID有序地列出了所有步骤。每个步骤的Action、Expected、Actual对比一目了然并且截图以Markdown图片语法嵌入在GitHub、GitLab、Linear等支持Markdown的平台可以直接预览。报告的价值这份报告是你所有工作的结晶。你可以把它粘贴到GitHub Issue或Pull Request的描述中提供完整的验收上下文。作为上线Checklist的附件证明核心流程已经过验证。在团队站会或故障复盘时直接作为讨论的依据避免口述偏差。4. 集成实战与自动化测试框架结合browser-proof单独使用已很有力但与自动化测试框架结合才能发挥其最大威力。下面以 Playwright 为例展示如何无缝集成。4.1 在Playwright测试中嵌入证据收集假设我们有一个Playwright测试用例。我们可以在每个关键断言点后调用append_browser_proof_step.py来记录状态。import subprocess import json from pathlib import Path def append_proof_step(manifest_path, step_id, surface, action, expected, actual, status, screenshot_pathNone): 封装调用 append_browser_proof_step.py 的辅助函数 cmd [ ‘python3’, ‘skill/browser-proof/scripts/append_browser_proof_step.py’, ‘--manifest’, manifest_path, ‘--step-id’, step_id, ‘--surface’, surface, ‘--action’, action, ‘--expected’, expected, ‘--actual’, actual, ‘--status’, status, ] if screenshot_path: cmd.extend([‘--screenshot’, screenshot_path]) # 可以类似地添加 --console, --network 参数需要你先从浏览器上下文中提取并保存这些文件 subprocess.run(cmd, checkTrue) # 在测试用例中 def test_checkout_flow(page): manifest “/tmp/browser-proof.json” artifacts_dir Path(“/tmp/artifacts”) artifacts_dir.mkdir(exist_okTrue) # 步骤1: 访问登录页 page.goto(“https://staging.example.com/login”) screenshot_1 artifacts_dir / “login-page-loaded.png” page.screenshot(pathscreenshot_1) append_proof_step( manifest, “step-1-login”, “login”, “访问登录页 https://staging.example.com/login”, “页面成功加载显示登录表单”, “登录表单正常显示”, “passed”, str(screenshot_1) ) # 步骤2: 输入错误密码 page.fill(‘input[name“password”]’, “wrongpass”) page.click(‘button[type“submit”]’) # 假设我们预期会显示错误提示 error_message page.locator(‘.error-alert’) screenshot_2 artifacts_dir / “login-error.png” page.screenshot(pathscreenshot_2) actual_text error_message.inner_text() if error_message.is_visible() else “未找到错误提示元素” expected_text “密码错误” status “passed” if expected_text in actual_text else “failed” append_proof_step( manifest, “step-2-login-error”, “login”, “输入错误密码 ‘wrongpass’ 并点击登录”, f“页面应显示错误提示‘{expected_text}’”, f“实际显示‘{actual_text}’”, status, str(screenshot_2) ) # 如果失败了可以额外保存此时的console日志 if status “failed”: console_log_path artifacts_dir / “login-error-console.json” # 这里需要从page.context()中提取console日志并保存具体代码略 # append_proof_step(..., --consolestr(console_log_path))通过这种方式你的自动化测试不仅输出“通过”或“失败”还产出了一份附带完整视觉和上下文证据的详细报告。4.2 在CI流水线中自动生成与归档在GitHub Actions或GitLab CI中你可以在测试任务完成后添加一个步骤来生成和发布证据报告。# 示例 GitHub Actions 步骤 - name: Run Playwright Tests with Proof run: | python init_session.py # 初始化证据包 pytest --browser-proof-manifest/tmp/proof.json # 运行集成了proof的测试 python check_bundle.py # 检查完整性 python render_report.py # 生成报告 - name: Upload Browser Proof Report if: always() # 无论测试成功与否都上传报告 uses: actions/upload-artifactv4 with: name: browser-proof-report path: | /tmp/browser-proof.json /tmp/browser-proof-report.md /tmp/artifacts/这样每次CI运行后你都可以下载一个包含所有测试证据的压缩包。对于失败的测试审查者无需拉取代码和复现环境直接看报告和截图就能快速理解故障点。5. 高级技巧与疑难问题排查在实际使用中你可能会遇到一些特定场景或问题。这里分享一些进阶技巧和解决方案。5.1 处理动态内容与浮动元素截图问题使用Playwright截图时弹窗、下拉菜单等动态元素可能已经消失导致截图证据不完整。 解决方案在操作前等待元素稳定或专门为动态元素截图。# 等待弹窗出现并截图 page.click(‘button#show-dialog’) dialog page.locator(‘.modal-dialog’) dialog.wait_for(state“visible”) # 先对弹窗本身截图确保捕捉到 dialog.screenshot(path“artifacts/dialog-content.png”) # 再对整个页面截图体现上下文 page.screenshot(path“artifacts/page-with-dialog.png”) # 在proof步骤中可以引用多张截图或在action中说明5.2 关联网络请求与控制台日志browser-proof支持关联HARHTTP Archive文件和Console日志。在Playwright中你可以轻松捕获这些信息。# 启动上下文时启用网络和Console记录 context browser.new_context( record_har_path“artifacts/network.har”, # Playwright 也支持记录Console输出到文件但可能需要通过事件监听 ) page context.new_page() # 监听Console事件并写入文件 console_logs [] def on_console(msg): console_logs.append({ “type”: msg.type, “text”: msg.text, “location”: str(msg.location), “timestamp”: datetime.now().isoformat() }) page.on(“console”, on_console) # 测试结束后保存日志 with open(“artifacts/console.json”, “w”) as f: json.dump(console_logs, f, indent2)然后在append_browser_proof_step.py命令中通过--network和--console参数关联这些文件。注意通常一个HAR文件涵盖整个浏览器上下文的所有请求你可以将其关联到最相关的那个步骤或者在Action中说明“详见附带的network.har文件”。5.3 管理大型会话与证据文件当一个会话包含几十上百个步骤时清单JSON文件会变大图片等证据文件也会占用空间。清单管理JSON文件本身很小可以放心纳入Git管理。清晰的step-id命名规范如login-01-open,login-02-fill-username有助于阅读。证据文件存储对于CI环境建议将artifacts/目录作为构建产物上传到对象存储如AWS S3, GCS或专业的测试报告平台。在Markdown报告中可以使用指向对象存储的公开URL来代替本地路径。这需要对render_browser_proof_report.py脚本进行小幅定制将本地路径替换为URL。5.4 常见错误与排查FileNotFoundError当运行append_browser_proof_step.py时检查确保--manifest参数指向的JSON文件已由init_browser_proof_session.py创建。检查确保你拥有对该JSON文件的写权限。完整性检查报错“Missing artifact file: …”检查--repo-root参数是否设置正确它应该是包含artifacts/文件夹的那个目录的路径。检查在运行检查脚本时当前工作目录是否在--repo-root之外脚本是基于--repo-root来解析相对路径的。生成的Markdown报告中图片无法显示检查报告中的图片链接是相对路径如artifacts/screen.png。你需要确保报告.md文件和artifacts/文件夹的相对位置保持不变。最稳妥的方式是将它们放在同一个父文件夹下进行分发。步骤状态更新错误append_browser_proof_step.py是追加操作如果你对同一个step-id重复运行它会在清单中创建重复的步骤记录而不是更新。如果你需要修改某一步需要手动编辑JSON文件或者设计流程避免重复ID。6. 总结与个人实践建议使用browser-proof一年多它已经从一个小工具变成了我们团队质量保障流程中的标准一环。它带来的最大改变是沟通成本的降低和证据质量的提升。现在当我们说“这个bug在Chrome上复现了”后面跟着的一定是一个包含完整操作、前后截图、网络日志的Proof链接讨论可以立刻聚焦在技术细节上而不是在“你做了什么”、“我看到了什么”这些基础信息上来回拉扯。对于想要引入browser-proof的团队我的建议是从小处着手不要一开始就要求所有测试都集成。可以先在手工验收关键功能时使用让团队成员熟悉“证据链”的思维方式。制定简单规范约定session-id的命名规则如日期-功能-负责人、artifacts的目录结构、以及什么情况下必须附加Console/Network证据例如所有失败步骤、所有涉及API调用的步骤。与工单系统结合鼓励团队成员在提交Bug或验收任务时附上browser-proof生成的Markdown报告内容而不是零散的截图。许多现代工单系统如Linear, Jira都完美支持Markdown。考虑轻量级定制browser-proof的脚本很简单你可以根据团队需求进行修改。例如修改报告模板以符合公司品牌或者增加一个将证据包自动上传到内部文件服务器的脚本。最后工具的价值在于使用。browser-proof提供了一套极佳的理念和基础实现。当你开始有意识地将每一次浏览器交互都视为需要记录和验证的“事件”时你会发现软件交付过程中的模糊地带变少了团队的协作也会变得更加清晰和高效。