为什么"无法复现"几乎都是步骤的问题
好的复现步骤 = 一个明确的起点 + 每一步一个动作 + 具体数据 + 每步的观察结果。 别人照着念一遍就能走到同一个画面,步骤就算合格。下面给出 5 条规则、粒度判断标准、5 个完整示例(含间歇性 Bug 的写法),以及一份提交前的自检清单。
开发回一句"我复现不了",九成不是不想查,而是步骤里少了东西。断点通常只有三类:
+ 号时才出现。一句话:步骤不是给你自己看的记录,是给别人走的路线图。
好步骤的 5 条规则
user+test@x.com,不要写"一个邮箱"。步骤粒度:写到多细才够
| 粒度 | 示例 | 问题 |
|---|---|---|
| 太粗 | "打开结算页,删除商品,发现数量不对" | 三个动作压成一句,无法判断在哪一步出错 |
| 刚好 | "1. 进入 /cart 2. 点击商品右侧的『删除』 3. 观察页面顶部角标" |
一步一个动作,可逐条核对 |
| 太细 | "1. 移动鼠标到按钮上 2. 按下左键 3. 松开左键" | 把物理操作拆开,反而更难读 |
判断标准:写完问自己两句——① 另一个人不看截图,能不能走到同一个画面?② 开发能不能在 2 分钟内判断问题出在前端、接口还是数据?两句都能答"是",粒度就对了。
5 个完整示例
示例 1:登录与鉴权(5 步)
前置条件:已注册账号 test@example.com,账号状态正常。
环境:Chrome 120 / macOS 14 / 桌面端 / 1920×1080 / 无痕窗口。
https://app.example.com/logintest@example.com 与正确密码期望:提示"验证码错误,请重试",账号不被锁定。 实际:提示"账号已锁定,请 24 小时后重试",此时验证码是正确的。
示例 2:支付与优惠(6 步)
前置条件:购物车中已有 2 件商品,合计 ¥1,299;账号为企业类型。 环境:Chrome 120 / Windows 11 / 桌面端 / 1440×900 / 企业账号。
/cart,确认合计金额为 ¥1,299SAVE100(该码已过期 3 天)期望:提示"优惠码已过期",购物车内容不变。 实际:提示"优惠码可用"并抹去 ¥100;点击「应用」瞬间购物车里的 2 件商品被清空。
示例 3:移动端触控(5 步)
前置条件:已登录,购物车中已有 1 件商品。 环境:iPhone 14 / iOS 17.2 / Safari / 视口 390×844。
https://shop.example.com/cart期望:「提交订单」按钮上移至键盘上方,可正常点击。 实际:键盘遮挡按钮约 60%,按钮区域无法响应点击。
示例 4:接口与数据(4 步)
前置条件:已获取测试环境 token;数据库中存在 12,400 条订单,其中匹配关键词的记录 12 条。
环境:测试环境 https://api-test.example.com / curl 8.x。
GET /api/orders/export?month=2026-08,请求头带 Authorization: Bearer <token>month 参数改为 2026-08-01~2026-08-07 后重试期望:返回 200 与导出任务 ID,或返回 202 表示任务已入队。 实际:返回 504(网关超时);缩小时间范围后返回 200,说明阈值与数据量相关。
示例 5:间歇性 Bug(含概率与时序)
前置条件:账号无余额,测试账户已绑定测试卡。 环境:Chrome 120 / macOS 14 / 网络限速至 3G。
/checkout 并填好支付信息期望:仅生成一笔订单;重复点击应被前端去重或后端幂等拦截。
实际:10 次测试中 3 次生成两笔订单(必现条件:间隔 <500ms + 网络延迟 >1s)。附 Network 面板录屏与两次 POST /api/orders 的请求 ID。
间歇性 Bug 的写法要点:
- 写概率,不写"偶发":"10 次中 3 次"比"偶发"有用一百倍。
- 写时序或阈值:"间隔 <500ms""网络延迟 >1s",这类条件往往是根因线索。
- 写证据类型:录屏与控制台日志是间歇性 Bug 唯一能带走的证据。
7 个让步骤作废的常见错误
提交前自检清单
- 前置条件(登录状态 + 数据状态)写了吗?
- 起点是业务动作,而不是"打开浏览器"?
- 每个编号只有一个动作?
- 数据是真实值,不是占位符?
- 关键步骤后写了观察到的现象?
- 期望结果与实际结果分开了?
- 间歇性 Bug 写了概率与时序?
常见问题(FAQ)
复现步骤写几步比较合适?
通常 3–8 步。少于 3 步往往缺少前置条件,超过 8 步大概率可以精简——把导航部分挪进前置条件,只保留触发问题的必要动作。
环境信息写在步骤里还是单独字段里?
单独字段。写进步骤会打断阅读节奏,也无法被筛选统计。若报告载体没有环境字段(例如发邮件),则在步骤开头用一行声明"环境:Chrome 120 / macOS 14 / 1920×1080"。
像"点击返回""关闭弹窗"这种无关操作要写吗?
只有当它是复现条件时才写。判断方法:把它删掉,问题还复现吗?还复现就删掉,不复现就必须留下。
自己都复现不了的 Bug,步骤怎么写?
如实写三件事:① 已尝试过的条件(哪几次成功、哪几次失败);② 能拿到的最强证据(录屏、控制台日志、网络请求);③ 观察到的相关性("只在网络慢的时候出现")。同时在标题或备注里标注"待确认复现条件",不要伪装成必现。
复现步骤和测试用例有什么区别?
测试用例是事先设计的验证清单(覆盖正常路径、边界与异常,追求覆盖率),复现步骤是事后记录的一条路径(只求把问题稳定重放)。两者的写法可以互相借鉴,但目标不同——测试用例的写法见 测试用例模板与示例。
步骤写对了,剩下的可以自动补齐
复现步骤本身必须由提交人写——只有你知道自己点过什么。但陪它一起提交的环境与证据,可以自动完成:
- 录屏:一键录制当前标签页并裁剪片段,间歇性 Bug 也有可回放的证据。
- 诊断数据:自动收集错误级控制台日志与失败的网络请求(HTTP ≥ 400),敏感参数自动脱敏。
- 自动技术信息:URL、浏览器、操作系统、分辨率与视口尺寸自动写入,不必手抄。
- 标注截图:拖拽选区加箭头、方框、文字,把出错位置固定在图上。
- 分享或同步:生成免注册即可查看的分享链接,或把报告送进飞书多维表格 / 通用 Webhook。
延伸阅读
- Bug 报告格式(10 个字段规范)
- Bug 报告模板(可复制骨架与填写示例)
- bug 标题示例(40 组好标题与差标题对照)
- 测试用例模板与示例
- 如何高效报告 Bug