# 缺陷报告怎么写才有用：为什么“标题写原因”和“步骤写全流程”都会拖慢修复

讲清最小复现步骤怎么剪、标题为什么只写现象、实际结果与预期结果怎么对照、环境版本与证据要附到什么程度，以及复现不了的问题该不该报

> 缺陷与失效 · 测试用例设计 · 测试基础 · 约 8 分钟 · 10 月 19 日

## 本篇要点

1. 缺陷报告要完成的是一次转移：让开发在他自己的机器上看到同一个现象，并知道它和你认为正确的行为不一致。判据是“他看完还要不要回来问你”。
2. 复现步骤要往回删到删不动，剩下的每一步都是触发问题所必需的；删不掉的账号、数据、开关移到前置条件里，“其余字段保持默认值”这类不做的事也要写明。
3. 标题写位置、动作和看到的结果，不写猜测的原因；原因在调试前只是假设，写进标题会把排查引偏，而现象是双方都能验证的事实。标题同时决定这个缺陷能不能被搜到、被判为重复。
4. 预期结果从事例里原样搬过来（执行前就已定义），实际结果只记录观察到的表现，两者分开写，并补上“不该发生什么”，数据层面的异常往往比界面更能定位。
5. 环境里最要紧的是最早能复现的构建版本：开发用它找引入问题的改动，测试用它区分症状相似但根因不同的缺陷。
6. 证据的标准是能印证“实际结果”里的每句话；只截相关的那一次请求和带时间戳的日志。
7. 报告必须标明可复现程度。完全无法复现的报告常常只是消耗开发时间，除非它能带来关于出现条件的独特信息；后果严重（崩溃、丢数据、算错金额、越权）时即使只出现一次也要报。
8. 一份报告只放一个缺陷，否则会出现修一半、另一半个被关掉却无人跟踪的状态。

---

上一篇收在一张能交给别人执行的用例表上。真跑起来，总有一条会失败：你按步骤操作完，屏幕上出现的东西和预期结果不一致。

这时你手里其实只有一个现象——“我做了这些动作，看见了那个”。缺陷报告要做的事只有一件：**把这个只发生在你这台机器上的现象，搬到开发手上，让他也能看见同一个现象，并且知道它和你认为对的那件事不一致。**ISTQB 对缺陷报告目标的描述就是这样：让开发能用一个最小的复现测试把问题隔离出来，然后修掉它 [3]。

所以判断一份报告够不够用，只要问一句：**他看完还要不要回来问你。**下面每一步，都在替对方回答一个他一定会问的问题。

## 动笔之前：先留住现场

截图、控制台报错、那一次请求的响应、日志行、列表里那条记录的实际值，都有时效性。页面一刷新、服务一重启、日志一滚动，现场就没了，再想补只能靠回忆，而回忆写出来的“实际结果”通常已经掺了自己的解释。

所以发现结果不符时，第一反应不是“我是不是看错了”，而是先把现场存下来，然后才重跑一遍，确认它是不是稳定出现。顺序反了，你会花半小时跟开发争论“到底有没有出现”，而不是修它。

## 第一步：把复现步骤剪到最短

你实际走过的是完整路径：登录后台 → 进商品管理 → 点促销 → 新建优惠活动 → 填名称和起止时间 → 选“按比例抵扣” → 比例填 0 → 保存。整串都能复现，但直接贴上去不算好步骤。

**做法是从完整路径往回删**：删掉一步，重跑一次，还能复现就继续删。删不动的那一步，就是真正的触发条件。对着上面那条路径删下去，常会剩下这样三条：

1. 用管理员账号登录后台，打开“新建优惠活动”页；
2. 在“抵扣比例”一栏输入 `0`；
3. 其余字段保持默认值，点击“保存”。

第 3 步那句不能省。你一省，开发顺手填了活动名称、选了日期，可能走了另一条分支，然后回你一句“我这儿正常”。

删不掉的账号角色、已有数据、功能开关，挪到“前置条件”里单独说，别混在编号步骤中间；数字要写具体，写“加 1 件有库存的商品”，不写“加几件商品”。

最小化有三层收益：别人照着能走通；开发看得出是从哪一步开始不对；这组步骤本身可以改写成回归用例。还有一点别做反了——如果删掉某一步现象就消失，那一步必须留着，并写明“少了这步就不出现”，这本身就是有价值的线索。

## 第二步：标题写现象，不写原因

标题要独立回答三件事：**在哪儿、做了什么、看到什么。**

- 可用：“抵扣比例输入 0 保存成功，范围校验提示未出现”
- 不好：“抵扣比例校验有问题”——太笼统，别人搜不到，也没法判断是不是已有缺陷
- 更糟：“前端漏了校验”——这是原因，不是现象

WebKit 的指南把这条讲得很直接：标题应当说明问题本身，而不是你建议的解决方案 [2]。Mozilla 的对照是：`Canceling a File Copy dialog crashes File Manager` 是好标题，`Software crashes` 是坏标题 [1]。

为什么不写原因？因为在有人调试之前，原因只是你的猜测；它一旦进了标题，就成了别人排查的前提。猜错时开发顺着错方向查半天，最后反过来怀疑报告。而现象是双方都能当场验证的事实。

标题还有第二个功能：**被搜索和去重**。同一个缺陷被两个人报是常事，只有标题里带着具体字段、具体取值、具体结果，第二个人才搜得到第一个人的报告。确有靠谱的原因线索，就写进“补充信息”并标明是推测。

## 第三步：实际结果和预期结果分开摆

两行，对照着写。只写“实际”，读的人得自己猜什么才算对；只写“预期”，他又不知道实际发生了什么 [3]。

**预期结果直接从事例里搬过来，不要现在编。**上一篇讲的就是这个：预期结果在执行前就定好了，它是你判这条用例失败的尺子。报告里原样抄那一行，等于把尺子交给开发看。临时补的预期结果，多半是照着实际结果倒推出来的，那就不是判据了。

**实际结果只写看见的，不带评价：**

> 点击“保存”后页面回到活动列表，列表新增一行，抵扣比例一栏显示 `0`，活动状态为“进行中”，页面没有任何提示；进入该活动详情页，折扣金额显示 `¥0.00`。

“保存有问题”“校验没生效”都不算实际结果，因为下一个读的人得先相信你的判断。

顺手把“不该发生什么”也写出来。上面这段里最有分量的一句其实是“列表新增了一行”——本该一条记录都没有。数据层面的实际结果，往往比界面上的表现更能帮人定位。

## 第四步：环境与数据，写到别人能重建

要写：构建版本号、操作系统与浏览器版本、环境（测试／预发）、账号角色与权限、关键数据的状态、相关配置开关。

**版本号最要紧，而且有讲究：写最早能复现问题的那一个版本。**开发拿它缩小范围，找出是哪次改动引入的回归；测试拿它区分“症状一样但根因不同”的缺陷——同一个版本出现的很可能是重复，不同版本出现的通常是两个问题 [1]。这一行常常直接决定报告的价值：如果现象在 `4.18.1` 不出现、`4.18.2-rc2` 才出现，事情的性质就不一样了。

环境不能省的理由很实在：缺陷经常不在代码里，而在配置和数据里。开发在他那边重现不出来，最常见的解释就是他的账号没这个权限、他的数据里没有那条已下架的记录。

## 第五步：附上能印证“实际结果”的证据

标准只有一条：**证据要能印证你写在“实际结果”里的每一句话。**

- **截图**：带能定位位置的上下文（页面标题、菜单）和出错的那段文案；只截一个输入框，别人不知道这是哪个页面。
- **请求与响应**：那一次请求的方法、URL、状态码和响应体。接口返回 `200`、响应体里是 `"ratio": 0`，比“保存成功”四个字有力得多。
- **日志**：带时间戳，只截相关的那一次。整个日志文件粘上去，重点就被埋了。
- **数据**：列表或数据库里那条记录的实际值。
- **录屏**：步骤难用文字描述时（拖拽、时序）。

## 第六步：说清它能不能稳定复现

三种情况，必须标明是哪一种：**稳定**（每次都出现，写“按上述步骤 3 次，3 次均复现”）、**偶现**（给出次数和当时条件）、**一次**。

Mozilla 的指南在这点上很直白：完全无法复现的问题，除非能提供关于它出现条件的独特信息，否则报上去基本没用 [1]。开发拿到一份“我这儿也复现不了”的报告，只能反复试、反复问，最后关掉，这段时间全赔进去了，而报告人往往觉得“报了就算尽责”。

但“复现不了”不等于不该报。如果现象是崩溃、数据丢失、金额算错、越权访问这类后果严重的问题，哪怕只出现一次也要报，因为你手上有开发没有的东西：你的数据、你的操作时序、你当时在做什么。这时把能记的都记上——次数、时间点、当时是否连点、网络是否切换过。偶现的写法可以是：“staging 环境，10 次操作出现 3 次，都是连续快速点两次‘保存’之后。”这已经把范围缩小了一半。

```mermaid
flowchart LR
  A["失败现象"] --> B{"重跑几次还在吗？"}
  B -->|"每次都出现"| C["写成最小步骤，标 3/3 复现"]
  B -->|"偶尔出现"| D["记下次数与当时条件，一并写进报告"]
  B -->|"再没出现"| E{"后果严重吗？"}
  E -->|"崩溃、丢数据、算错钱"| F["照报，附现场记录并标明推测"]
  E -->|"只是界面小瑕疵"| G["先记录，等有更多线索再报"]
```

## 交出去之前，过一遍三个问题

1. 别人照这些步骤，能不能在他自己的机器上看到同一个现象？不能，就补环境和数据。
2. 他只看“实际”和“预期”两行，能不能判断这算不算错？不能，就是两项没分开写。
3. 他相不相信你说的？不信，就补证据。

再加一条习惯：**一次只报一个缺陷。**一份报告里塞两个问题，容易出现“修了一个、另一个跟着被关掉”的状态，后面谁也追不回来 [1]。

最后留个接口：报告里还有一栏叫“影响多大”，它最容易挨开发的反驳——因为它和“多急”不是同一件事。下一篇就讲严重程度和优先级怎么定。

## 术语表

- 最小复现步骤：从完整操作路径里逐步删减、每删一步重跑验证后剩下的那组动作，其中每一步都是触发问题所必需的。
- 可复现程度：同一组动作重复执行时现象出现的比例，分稳定复现、偶现、只出现一次三种，决定这份报告能否被接手。
- 构建版本号：标识这次测试的是哪一次打包产物，用来判断是不是回归、以及区分症状相似而根因不同的缺陷。
- 失败现场：失败发生那一刻的屏幕、日志、请求响应和数据取值，刷新或重启后无法恢复，必须在确认问题之前留住。

## 来源

1. [Mozilla Bug Writing Guidelines — 标题与最小复现步骤的要求、事实与推测分开、一次一报、版本选择与可复现性判断](https://bugzilla.mozilla.org/page.cgi?id=bug-writing.html)
2. [WebKit Bug Writing Guidelines — 摘要应说明问题而非建议的解决方案，以及步骤、实际与预期结果的填写方式](https://bugs.webkit.org/page.cgi?id=bug-writing.html)
3. [ISTQB 5.6 Defect Management — 缺陷报告的目标（用最小复现测试隔离问题）与典型字段清单](https://davits.page/istqb/5.6-defect-management/)

---

原文：https://pangzhengboyin.com/articles/how-to-write-an-actionable-bug-report-04bfac31

> **庞征博引** · 想学的，慢慢都会
>
> 庞征博引是把想学的东西写成连载的 AI 学习工具。说出想学什么，它会先了解你的基础，再把主题写成一篇篇 5–10 分钟能读完的文章；边读边问，接下来学什么跟着你走。这篇就是这样写出来的。
>
> 开始你自己的连载 → https://pangzhengboyin.com
