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

这时你手里其实只有一个现象——“我做了这些动作,看见了那个”。缺陷报告要做的事只有一件:把这个只发生在你这台机器上的现象,搬到开发手上,让他也能看见同一个现象,并且知道它和你认为对的那件事不一致。 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 次,都是连续快速点两次‘保存’之后。”这已经把范围缩小了一半。

绘制中

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

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

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

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