
摘要手工复现网页 Bug 低效且依赖人工扫码登录本文分享如何从零创建一个基于 Playwright-MCP 的 bug-reproduce 技能技能文件怎么组织、扫码登录如何自动化处理截图二维码→等待扫码→会话持久化免重复登录、如何一键复现真实 Bug 并定位根因。附一个「跟进事项详情页显示 code 而非昵称」的完整实战案例步骤清晰可照做。目录一、背景与痛点二、方案设计三、技能创建步骤四、实战执行扫码登录与会话保持五、实战执行真实 Bug 复现六、验证结果与踩坑总结一、背景与痛点作为测试工程师日常最耗时的事情之一就是复现网页 Bug测试环境需要扫码登录企业微信/微信自动化脚本根本扫不了码每次都要人工介入复现步骤全靠手工点操作路径不固定截图、控制台报错、网络请求要分开抓效率极低复现结果不可沉淀这次定位到了下次回归还得重来一遍想写 pytest-playwright 自动化用例但卡在登录态——测试跑起来第一步就过不去。本文要解决的问题就是把「复现 Bug」这件事做成一个可复用的技能扫码登录只做一次之后全程免登录自动复现。二、方案设计核心思路一句话用一个 Skill 把「登录处理 浏览器操作 诊断采集 脚本生成」串成固定流程交给 Playwright-MCP 执行。设计要点需求方案扫码登录自动化检测登录墙 → 定位二维码 → 截图提示用户扫码 → 轮询等待登录完成免重复登录登录成功后保存storage_state下次运行先恢复会话真实用户操作用 Playwright-MCP 的 navigate / click / type / select_option 逐步模拟诊断信息采集关键节点截图、console 错误、异常网络接口一并收集结果可沉淀输出分析报告 生成可运行的 pytest-playwright 复现脚本技能文件组织AtomCode 技能约定目录名用 U2011 非断行连字符~/.atomcode/skills/ └── bug‑reproduce/ # 技能目录U2011 连字符 ├── skill.md # 触发说明 流程概述 ├── skill.json # 技能元数据名称/描述/版本/标签/入口 └── system-prompt.md # 完整执行指令登录墙处理、复现流程、输出要求三、技能创建步骤3.1 创建skill.md触发说明文件头部用 frontmatter 声明技能名称与描述正文写流程概述让模型一眼知道「这是干什么的、关键步骤是什么」--- name: bug‑reproduce description: Playwright‑MCP自动复现网页bug支持扫码/账号登录墙处理与会话保持自动截图、抓取浏览器日志、输出分析报告生成复现脚本 --- # Bug ReproducePlaywright‑MCP 复现 你是测试工程师接收用户提供的 bug 地址、复现步骤。 调用 playwright‑mcp 完成浏览器操作 ## 流程 0. **会话恢复下次免登录**复现开始前若存在 bug_reproduce_auth_state.json 先 browser_set_storage_state 恢复登录态再打开地址跳过扫码。 1. **打开地址并处理登录墙**重点 - 若站点需要登录如扫码登录先完成登录再复现 1. 定位二维码并截图保存到 ./bug_screenshot/login_qr.png提示用户扫码 2. 轮询等待登录完成登录墙消失超时则如实报告等待 3. 登录成功后 browser_storage_state 保存会话到 bug_reproduce_auth_state.json 并告知用户下次免登录。 2. 按照复现步骤模拟用户真实操作 3. 关键节点截图保存本地 ./bug_screenshot 4. 采集浏览器 console 错误、异常网络接口。 ## 输出 1. 复现结论是否稳定复现 bug 2. bug 现象、控制台报错、异常接口清单 3. 根因初步分析 4. 完整 pytest‑playwright 复现脚本写入本地 bug_reproduce.py含登录态恢复逻辑。 ## 约束 - 扫码等无法自动化的步骤明确告知用户并等待不假装成功 - 截图/日志文件统一放 ./bug_screenshot/。3.2 创建skill.json元数据声明技能名称、描述、版本、标签和入口文件entrypoint指向system-prompt.md{name:bug-reproduce,description:Playwright-MCP自动复现网页bug自动截图、抓取浏览器日志、输出分析报告并生成pytest-playwright复现脚本内置扫码登录/账号密码登录墙处理与会话保持,version:1.1.0,author:AtomCode,tags:[bug复现,playwright,UI测试,扫码登录,浏览器自动化],entrypoint:system-prompt.md}3.3 创建system-prompt.md完整执行指令这是技能的核心重点写清楚「登录墙处理」——尤其是扫码登录的完整闭环# System Prompt — Bug 复现Playwright‑MCP ## 一、登录墙处理扫码登录 / 账号密码登录 ### 0. 会话恢复下次免登录 - 复现开始前若本地存在 ./bug_reproduce_auth_state.json先调用 browser_set_storage_state 恢复登录态再打开地址可直接跳过扫码 - 恢复后仍需检测是否落在登录墙若仍被拦截说明会话过期重新登录并更新保存。 ### 1. 检测是否需要登录 - 打开地址后先 browser_snapshot并检查 URL 是否包含 login、signin、auth 等关键字 - 页面出现「登录」「扫码登录」「请登录」等元素即判定存在登录墙。 ### 2. 扫码登录流程优先 1. 用 browser_snapshot 定位二维码元素通常是 img 或 canvas 2. 用 browser_take_screenshotelement 指向二维码截取二维码保存到 ./bug_screenshot/login_qr.png 3. 打开图片提示用户扫码并说明「已等待扫码登录完成后自动继续」 4. 轮询等待登录完成每 5-10 秒检查一次登录墙是否消失URL 变化 / 登录元素不可见 / 出现登录后特征元素总超时建议 120 秒 5. 登录成功后调用 browser_storage_state 保存会话到 ./bug_reproduce_auth_state.json 并告知用户「登录态已保存下次免登录」。 ### 3. 账号密码登录用户提供凭据时 - 用 browser_fill_form / browser_type 填写账号密码并提交 - 有验证码/二次验证时截图告知用户手动处理。 ### 4. 登录失败处理 - 扫码超时如实报告「登录未完成」请用户手动登录后继续 - 二维码过期重新截图最新二维码 - 严禁在未登录状态下假装复现业务 bug。 ## 二、复现执行 1. 按复现步骤逐步模拟用户真实操作navigate / click / type / select_option 等 2. 关键节点截图保存 ./bug_screenshot/stepNN_描述.png 3. 采集诊断信息browser_console_messages levelerror控制台报错、 browser_network_requests异常接口 4xx/5xx、必要时 browser_evaluate 读取页面状态。 ## 三、输出内容 1. 复现结论是否稳定复现 bug 2. bug 现象截图路径 现象描述 3. 控制台报错清单、异常接口清单 4. 根因初步分析 5. 完整 pytest‑playwright 脚本写入 bug_reproduce.py含会话恢复逻辑。 ## 四、约束 - 截图与日志统一存放 ./bug_screenshot/ - 无法自动化的步骤扫码、验证码明确告知用户并等待不编造成功结果 - 报告必须基于真实观察禁止虚构接口或报错。四、实战执行扫码登录与会话保持技能建好了用真实站点https://example.com/企业微信扫码登录走一遍完整流程。4.1 打开站点检测登录墙# Playwright-MCP 操作 navigate → https://example.com打开后自动跳转到登录页Page URL: https://example.com/login?redirect/dashboard/workbench Page Title: 登录 - M测试browser_snapshot发现页面包含 iframe「企业微信扫码登录 / 请使用企业微信扫描二维码登录」——登录墙确认。4.2 截取二维码提示用户扫码# 定位二维码所在 iframe 并截图 browser_take_screenshot (element企业微信扫码登录 iframe) → bug_screenshot/login_qr.png二维码图片保存到./bug_screenshot/login_qr.png并打开提示用户用手机扫码。这一步是技能与人的唯一一次交互。4.3 轮询等待登录完成browser_wait_for (textGone请使用企业微信扫描二维码登录, time120s)用户扫码后页面从/login?redirect...跳转到工作台Page URL: https://example.com/dashboard/workbench Page Title: 工作台 - M测试 出现提示登录成功欢迎回来运营人员4.4 保存会话验证下次免登录登录成功后立即保存登录态browser_storage_state → bug_reproduce_auth_state.json # 文件内容5 个 cookies 4 个 origins覆盖 example.com 与 wx.qq.com验证免登录闭环# 新会话先恢复登录态再打开站点 browser_set_storage_state → bug_reproduce_auth_state.json navigate → https://example.com 结果直接进入 /dashboard/workbench工作台 - M测试无登录墙、无需扫码 ✅从此以后技能每次执行都会先恢复会话、跳过扫码直达业务页面。4.5 会话复用的日常操作聚合聊天发消息免登录会话不止用于复现 Bug日常操作同样一条龙。例如给某个群发消息# 技能流程恢复会话 → 打开聚合聊天 → 定位群 → 发送 → 验证 navigate → https://example.com/c2b/contact/chat # 聚合聊天全部 83 / 单聊 9 / 群聊 74 type → 搜索聊天框输入「某快递」 # 搜索定位目标群 click → 进入「某快递合作群」群 type → 输入框填写「你好」 click → 发送按钮验证会话记录中出现运营人员你好13:38发送成功 ✅。整个流程无需登录、无需人工干预——会话持久化的价值在这里体现得最直接。五、实战执行真实 Bug 复现5.1 复现目标地址https://example.com/c2b/business/followup跟进事项 期望查看详情时客户和跟进人展示昵称 现象详情弹窗中客户和跟进人展示的是 code原始 ID5.2 会话恢复 打开页面技能按流程先恢复会话免登录再打开跟进事项页面。页面标题「跟进事项 - M测试」搜索框、状态筛选、表格均正常渲染。5.3 定位问题数据点「搜索」加载列表接口返回 378 条数据发现多条记录跟进人列直接显示 code| 客户 | 标题 | 跟进人 | |----------|----------------|----------------------------------------------------| | 客户A | 跟进示例任务 | CUST_XXXX_客户A_ID... | ← code | 客户B | 定期发送健康.. | CUST_XXXX_客户B_ID | ← code点击该行弹出「查看详情」确认问题客户 (combobox) : CUST_XXXX_客户A_ID ← 应为 客户A 跟进人 (combobox) : CUST_XXXX_客户A_ID ← 应为昵称截图取证bug_screenshot/followup_detail_code_bug.png。5.4 抓接口、定位根因查看网络请求三个关键接口全部返回 200不是接口故障是数据翻译链路问题接口返回结论follw/list200userId_dictText对部分记录原样返回 code翻译失败wwCcfuomer/follow-user200跟进人下拉数据源员工列表不含客户型跟进人wwuster/list?pageSize10200客户下拉数据源分页 10 条/页total686目标客户不在首屏根因分析两条原因叠加跟进人显示 codemodFllow记录的userId存的是客户自身 ID客户自建跟进任务不在员工跟进人表中 → 后端userId_dictText翻译失败、原样回传 code → 前端下拉框匹配不到选项直接渲染原始值。客户显示 code详情弹窗「客户」下拉框数据来自wwComer/list分页接口仅首屏 10 条目标客户不在已加载页 → 前端匹配不到 → 回退显示原始customerId列表接口其实已正确翻译customerId_dictText客户A前端未采用。修复方向后端dictText 翻译需兼容「跟进人客户」场景或前端优先使用列表接口返回的*_dictText。前端客户下拉框匹配不到时回退customerId_dictText或按 id 精确加载而不是显示原始 code。5.5 生成复现脚本技能按输出要求生成 pytest-playwright 复现脚本bug_reproduce.py bug_reproduce.py — 跟进事项详情「客户/跟进人显示code而非昵称」复现脚本 运行前提pip install pytest pytest-playwright存在 bug_reproduce_auth_state.json 运行方式pytest bug_reproduce.py -v importreimportpytestfromplaywright.sync_apiimportPage BASE_URLhttps://example.comAUTH_STATEbug_reproduce_auth_state.jsonTARGET_ROW_TITLE跟进示例任务# 该行跟进人 userId 为客户端ID最易复现def_open_detail_and_read_fields(page:Page)-dict:点击目标行打开详情弹窗读取 客户/跟进人 下拉框当前显示值。page.get_by_role(button,name搜索,exactTrue).click()page.wait_for_timeout(2000)page.get_by_role(row,namere.compile(TARGET_ROW_TITLE)).first.click()page.wait_for_timeout(1500)dialogpage.get_by_role(dialog)customer_combodialog.locator(div).filter(has_textre.compile(^客户)).locator(.ant-select)follower_combodialog.locator(div).filter(has_textre.compile(^跟进人)).locator(.ant-select)return{customer:customer_combo.first.inner_text().strip(),follower:follower_combo.first.inner_text().strip()}deftest_detail_shows_nickname_instead_of_code(page:Page):期望详情弹窗中客户/跟进人展示昵称而不是 code。page.goto(f{BASE_URL}/c2b/business/followup,wait_untildomcontentloaded)page.wait_for_timeout(5000)values_open_detail_and_read_fields(page)code_likere.compile(r^[A-Za-z0-9_\-]{16,}$)# 形如长串 code 的原始 IDassertnotcode_like.match(values[customer]),f[BUG复现] 客户显示 code{values[customer]!r}assertnotcode_like.match(values[follower]),f[BUG复现] 跟进人显示 code{values[follower]!r}六、验证结果与踩坑总结6.1 验证结果验证项结果扫码登录✅ 截图二维码 → 用户扫码 → 自动进入工作台欢迎回来运营人员会话持久化✅bug_reproduce_auth_state.json5 cookies 4 origins免登录复用✅ 恢复会话后直达工作台无登录墙聚合聊天发消息✅ 「运营人员你好」成功出现在群会话记录Bug 复现✅ 稳定复现「详情页客户/跟进人显示 code」复现脚本✅bug_reproduce.py生成py_compile语法通过、pytest 收集到 1 个用例6.2 踩坑总结扫码等待别用固定 sleep二维码可能过期、用户可能迟迟不扫。正确做法是browser_wait_for(textGone...)轮询登录墙消失并设总超时120s超时如实报告而不是假装成功。会话状态要主动保存登录成功 ≠ 下次免登录。必须显式browser_storage_state落盘并在每次执行开头browser_set_storage_state恢复否则重启浏览器就要重新扫码。接口 200 ≠ 数据正常本次 bug 三个接口全部 200问题出在 dictText 翻译链路上——排查时不能只看状态码要对比响应里的*_dictText字段是否翻译成功。列表有数据但页面显示「暂无数据」首屏可能未触发查询先点「搜索」刷新下拉框数据来自分页接口10 条/页匹配不到时前端会回退显示原始 ID这正是本次 bug 的触发点之一。技能目录命名AtomCode 技能目录名用 U2011 非断行连字符如bug‑reproduce指令文件为小写skill.md另配skill.jsonentrypoint指向system-prompt.md——与文档示例的SKILL.md大小写不同照文档示例建会导致加载失败。6.3 总结从零创建 bug-reproduce 技能到完成真实 Bug 复现核心收获有三点登录墙是自动化第一道坎用「截图二维码 → 人工扫码 → 轮询等待 → 会话落盘」四步闭环把扫码登录变成一次性成本技能把流程固化成资产skill.md / skill.json / system-prompt.md 三件套让复现步骤、诊断手段、输出规范全部可复用团队任何成员都能一键复现复现要落到根因和脚本不只说「复现了」还要抓接口对比 dictText、给出修复方向、生成 pytest-playwright 脚本让 Bug 从「现象」变成「可回归的用例」。标签#Playwright #MCP #自动化测试 #Bug复现 #技能开发