☰
测试用例编写指南:从需求检查点到颗粒度控制
2026/11/6 5:43:43 网站建设 项目流程

简介:这份测试用例编写指南面向测试人员与技术管理团队成员,针对用例设计凭惯性、划分颗粒度不一、可读性与质量参差等问题,给出可循的规范流程。文档从测试设计依据入手,依次讲清需求分析、业务流程分析、系统设计分析、用例编写与完善五个环节,并细化测试需求与用例模板要素、划分原则、编写要求、测试类型、等价类划分、边界值分析和状态迁移等设计方法,附有维护与风险建议。压缩包仅含1个docx文件,约494KB,便于直接查阅和团队内部分享。已有553人学习,适合希望统一用例编写口径、补齐设计方法、提升测试覆盖与投产质量的中初级测试人员。

1. 用例越写越多,覆盖率反而在降

大部分团队的测试用例数量年年涨,缺陷逃逸率却没降。翻一遍用例库就明白,问题不在写得少,而在颗粒度失控:同一个模块,一个人把整个下单流程塞进一条用例的预期结果里,另一个人把输入框长度校验拆成七条,评审时谁也说不清哪条更"完整"。一份能落地的测试用例编写指南,真正要解决的不是"字段怎么填",而是把"划分"从个人手感变成可复用的判定规则——这也是用例编写注意点里最容易被跳过的一段。下面沿着需求怎么变成检查点、检查点怎么变成用例、用例字段为什么只能长成这个样子往下拆。

2. 五步链路:需求文档到检查点的信息守恒

2.1 需求分析:按流程或功能分类,落到可判定的检查点

需求说明书是业务语言写的,检查点是可判定命题。这两者之间的翻译损耗,就是测试设计的第一道漏点。原文给出的处理方式是"将业务需求按流程或功能分类",输出"整理成测试需求,将每一个需求细节列出,作为检查点"。

这句话里最关键的是"检查点"三个字。一条需求写成"支持用户注册",它不是检查点,因为无法判定通过与否;拆成"手机号已被占用时前端提示'该手机号已注册'且后台无新增用户记录",才是检查点——它有输入、有触发条件、有可观测的判据。

分类这一步也不是为了好看。按流程分和按功能分,会得到两种截然不同的检查点密度。按功能分(用户管理、报表管理、模板管理),切的是系统的静态结构,适合覆盖功能清单的完整性;按流程分(合同登记、放款、审批),切的是系统的动态路径,适合暴露状态流转上的缺口。常见的实现思路是两条都走一遍:先用功能分类保证"需求清单一条不漏",再用流程分类保证"路径上的每个判断条件都被点到",两遍结果的差集,往往就是原需求文档写漏的地方。

2.2 业务流程分析:需求说明书没写的那一半

第二步的输入不是文档,而是"业务背景和知识,被测系统/模块的业务流程"。处理要求整理出主流程、备选流程、数据流向、关键判断条件,以及"完成该操作的(非)必要条件"。输出明确写着:这是"作为业务需求未提及、但需要覆盖验证的检查点"。

这一步存在的理由很实在。需求文档的写作视角是"系统要提供什么能力",而测试要验证的是"这条能力在真实业务链条里被调用时会不会断"。举例,一个放款流程,需求文档会写支持放款、支持撤销、支持复核;但业务上真实存在的路径是"支行经办 → 分行审核拒绝 → 重新提交 → 分行审核通过 → 总行审核通过",中间那次拒绝后的重提交,需求文档里通常没有独立章节,可它恰恰是状态机最容易出错的地方。

关键判断条件和"(非)必要条件"这两项,是把业务流程转成检查点的抓手。判断条件对应程序里的分支,一个条件不成立时系统该走哪条路,就是一个检查点;非必要条件对应那些"看起来该拦但业务上允许放行"的边界,比如某个字段在特定业务类型下可以为空,这种规则只存在于业务知识里,文档里查不到。

这里有个容易被忽略的设计取舍:这一步的输出是"补充检查点",而不是"补充用例"。检查点和用例分开,是为了让补充动作保持在需求层,避免流程分析阶段就掉进操作步骤的细节里,把链路拉长。

2.3 系统设计分析:改动点与影响范围如何变成回归检查点

第三步看的是另一类文档:概要设计、详细设计、接口设计、数据库设计。处理要求是"针对系统为实现业务需求所做的主要改动点及影响范围进行全面分析",输出"将改动功能支持的所有逻辑、以及对影响范围的回归测试加入测试需求检查点"。

这一步是整条链路里信息密度最高的。前两步回答"业务要什么",这一步回答"代码怎么实现的"。同一个业务规则,在不同实现下的检查点完全不同:如果金额计算放在数据库存储过程里,检查点必须包含数据表关键字段的落库结果;如果放在应用层,检查点就要落在接口返回和日志上。

"影响范围"是这段里最有价值的一句。测试设计里真正的血泪经验,基本都来自影响范围判断失误——改了一个报表模板的字段长度,结果把引用该表的批处理任务搞挂了。设计文档能提供的线索包括:被改动的表被哪些模块引用、被改动的接口被哪些上游调用、被改动的公共方法出现在哪些流程里。把这些线索逐条转成回归检查点,才算完成这一步。

我一般会这么理解:需求分析和业务流程分析产出的是"这个功能该测什么",系统设计分析产出的是"这次改动会波及什么"。前者是功能维度的覆盖,后者是变更维度的覆盖,两者是正交的,缺一个都会漏。

2.4 五步串行而非并行:信息在每一步衰减

四个分析步骤加上最后的用例完善,是一条单向链路,中间不回头。这个顺序不是流程洁癖,是被信息衰减规律逼出来的。

假设跳过业务流程分析直接写用例,写出来的用例只能覆盖需求文档字面描述的部分,业务流程里的备选路径全部丢失;假设跳过系统设计分析,用例的预期结果就只能写到"页面提示成功",无法落到"XX 表新增一条记录且状态字段为 1",而后半句才是真正能抓住缺陷的断言。

链路末端是"测试用例完善",触发条件列了五条:评审发现用例有问题、系统新增功能或需求变更、测试过程中发现设计时考虑不周、系统出现生产问题且经分析为测试泄漏。第四条最关键——生产问题反推回用例,是唯一能校准整条链路准确性的反馈信号。缺了这条回路,链路就只是流程,不是机制。

提示:四个分析步骤的输出都应该停在"检查点"这一层,不要提前写操作步骤。检查点是"要验证什么",操作步骤是"怎么验证",混在一起写会让需求阶段的评审失去焦点。

3. 用例要素的字段设计:每个字段为什么必须存在

3.1 需求路径与用例路径:多一级"/需求名称/"的意义

需求侧要素是五个字段:需求路径、需求名称、需求描述、设计人、关联系统。用例侧是十二个:用例路径、测试名称、用例描述、前置条件、操作步骤、预期结果、设计人、优先级、用例类型、用例属性、测试方式、执行次数。

两侧都有路径字段,格式不同。需求路径是"/项目名称/一级需求/二级需求/……/N 级需求",用例路径是"在需求路径的基础上增加需求名称",即末尾多挂一级。

这一级不是冗余。需求路径标识的是"这块业务在系统里的位置",用例路径标识的是"这条用例验证的是哪个需求下的哪个检查点"。少了这一级,一个末级需求下有十几个检查点时,所有用例平铺在同一层,既无法按需求统计覆盖情况,也无法在需求变更时精准定位受影响的用例集。

用一段结构化的数据表达会更清楚:

# 一条用例的完整路径链路,从项目根节点一路挂到需求节点 path: project: "模拟项目X" # 项目名称,路径根节点 level_1: "业务管理" # 一级需求,通常对应系统模块 level_2: "其他业务" # 二级需求,对应子模块 level_3: "财务报表" # 三级需求,对应功能组 requirement: "财报模板管理" # 需求名称,用例路径的末级 # 用例侧的十二个要素 case: name: "财报模板删除_模板已被引用" # 测试名称,能直接识别对象和检查点 description: "验证被引用的模板不可删除" # 用例描述 precondition: # 前置条件,完整列出且不依赖其他用例 - "指定用户具备模板管理权限" - "存在一个已被报表任务引用的模板" steps: ["进入模板管理页", "选中目标模板点击删除"] # 操作步骤,不含检查结果 expected: ["系统提示模板已被引用,删除失败", "模板记录仍存在于 XX 表且状态不变"] designer: "A同学" # 设计人 priority: "中" # 高/中/低 case_type: "功能点类" # 流程类/功能点类/报表统计类/界面类/报文接口类/批处理/其他 attribute: "异常" # 正常/异常 test_mode: "手工" # 手工/自动化 exec_count: 1 # 执行次数

结构里能看到一个设计意图:路径是树,要素是叶子。树负责可检索,叶子负责可执行。把这两件事塞进同一个字段,就会出现"用例名里带一长串层级"这种既不好读也不好查的写法。

3.2 前置条件:为什么"用例之间不允许相互依赖"是硬约束

编写要求里对前置条件有两条:有特殊账号权限、需要数据准备或前置操作的用例,必须完整列出;"用例之间不允许相互依赖,例如:将其他用例作为前置条件"。

第二条是硬约束,不是建议。原因在于执行模型:用例在测试管理平台里是可以被单独选中、单独执行、单独标记结果的。一旦 A 用例的前置条件写成"先执行 B 用例",A 就失去了独立性——B 挂了,A 无法执行;B 改了,A 的结论不可信;只跑 A 不跑 B,结果就是脏的。

更隐蔽的问题是数据污染。把"上一条用例创建的订单"当成前置条件,等于把两条用例绑在同一份数据上。执行顺序一变,或者中间有人手动改了一次数据,整组结果全部作废,且无法定位是哪一步坏的。

正确的处理是把前置状态写清楚,而不是写"执行某条用例"。要写"系统中存在一笔状态为待审核的订单,金额 1000 元,由指定用户创建"。这样无论是手工准备还是脚本预置,都能独立复现这个起点。

3.3 操作步骤与预期结果的分离:一条不能越界的双边约定

编写要求对这两个字段各写了一条禁令,方向相反:

  • 操作步骤中不能包含检查结果;
  • 预期结果中不能包含操作步骤。

这条双边约定解决的是执行人的认知负担问题。操作步骤是"手要做什么",预期结果是"眼要看什么"。一旦操作步骤里混进"点击保存,确认提示成功",执行人就会在点完按钮的瞬间下判断,而此时数据还没落库、异步任务还没返回、页面刷新还没完成——这一步判断大概率是错的。

反过来,预期结果里写"点击查询按钮,列表显示 10 条记录",执行人就得先回头找按钮在哪,再看结果,两件事搅在一起。

预期结果这一侧还有几条更细的要求,值得单独看:

  • 前端操作成功/失败,应包含页面显示、提示信息、后台数据存储、前后端数据一致性检查;
  • 如涉及后台数据存储/变更,应明确具体数据表记录和关键字段取值变化;
  • 提示信息应明确关键检查内容;
  • 后台系统测试和涉及信息安全的前端操作测试必须包含输出日志、后台数据存储结果检查。

第一条把"成功"这件事拆成了四层:页面、提示、存储、一致性。只写"操作成功"是把四层压成一层,等于放弃了后三层的缺陷发现能力。第二条把"存储"再落到表和字段,从"数据正确"变成"XX 表新增一条记录,状态字段为 1,创建时间为当前时间"——后者可判定,前者不可判定。

3.4 优先级、用例类型、属性、测试方式:四个正交维度

这四个字段经常被当成一个字段用,实际各管一摊:

字段取值回答的问题常见误用
优先级高/中/低先跑哪条把"重要功能"全打成高,高优先级占比过半
用例类型流程类/功能点类/报表统计类/界面类/报文接口类/批处理/其他这条用例测的是哪类对象批处理用例标成功能点类,统计时对不上
用例属性正常/异常这条用例走的是正向还是反向边界值用例标成正常
测试方式手工/自动化由谁执行自动化用例拆得比功能用例粗,覆盖不上

优先级的划分规则原文写得很具体:高是"确保系统基本功能及关键路径",如正常流程、页面元素正常输入;中是"确保系统功能完善",如异常流程、页面元素异常输入;低是"关于用户体验、及其他较少使用或辅助功能",如页面元素显示。

这里有个反直觉的点:页面元素显示测试被划到低优先级,而页面元素正常输入测试被划到高。原因不是显示不重要,而是显示问题的发现成本低、修复成本也低,在时间受限时应该先保证关键路径跑通。这是一条明确的取舍,不是主观偏好。

用例属性这一维度的价值在于统计口径。一个模块如果正常用例占比 80%、异常用例只有 20%,那基本可以判断这个模块的异常路径覆盖不足,不用逐条看用例内容。这比人工评审快得多。

4. 操作步骤与预期结果的分支映射:多对多怎么编号不歧义

4.1 四种映射关系的判定与代价

原文把操作步骤和预期结果分支的对应关系分成了四类,并明确其中一类不允许出现:

映射关系是否允许判定依据典型场景
一对一允许一个操作产生一个结果分支删除未挂用例的执行集
多对一允许多个操作指向同一个结果分支分别删除一级目录、多级根目录、多级子目录,结果都是删除成功
多对多允许(需编号配对)若干"多对一"分组的并列删除不同状态的执行集,结果分别为成功与失败
一对多不允许一个操作产生多个互斥结果分支一次点击既可能成功也可能失败

"一对多"被禁的理由:一条用例的结论只有"通过"或"失败"两个值。如果一个操作能产生两个互斥的结果分支,那这条用例实际在测两个不同的判定条件,执行人无论看到哪个分支,都无法给出一个整条用例的通过/失败结论。这种情况必须拆成两条用例。

而"多对多"之所以允许,是因为它本质上是多个"多对一"分组的并列——每个操作仍然落在唯一一个结果分支里,只是整条用例包含多个这样的组。用编号把组和组之间隔开,就回到了可判定的状态。

注意:多对多的编号配对不是格式要求,是判定逻辑。编号错了,一条本该失败的用例可能因为对错了分支而被判通过。

4.2 用编号配对把多对多收敛成可校验的结构

原文给的示例里,操作步骤写成"1、2、3"编号,预期结果写成"1-2:……;3-4:……"的范围编号,两组编号必须严丝合缝。这种写法可以做机器校验,比人工评审可靠。

下面这段检查逻辑做过简化,核心是三个判断:每个操作编号必须出现且只出现在一个预期分组里;预期分组不能为空;分组编号必须连续覆盖。

import re def check_step_expect_mapping(step_count: int, expects: list[str]) -> list[str]: """校验操作步骤与预期结果分支的编号配对是否合法。 step_count: 操作步骤总数,步骤编号从 1 开始 expects: 预期结果列表,每项以 "编号:" 或 "起-止:" 开头 返回: 问题列表,空列表表示通过 """ problems = [] owner = {} # 步骤编号 -> 所属预期分组索引 for idx, raw in enumerate(expects): # 解析行首编号,兼容 "1:" 与 "1-2:" 两种写法 m = re.match(r"^\s*(\d+)(?:\s*-\s*(\d+))?\s*[::]", raw) if not m: problems.append(f"预期结果第 {idx + 1} 条缺少编号前缀") continue start = int(m.group(1)) end = int(m.group(2)) if m.group(2) else start if start > end: problems.append(f"预期结果第 {idx + 1} 条编号范围非法: {start}-{end}") continue for step in range(start, end + 1): if step in owner: # 同一操作落到两个结果分支,等价于一对多,必须拆用例 problems.append( f"操作 {step} 同时对应预期 {owner[step] + 1} 与 {idx + 1},需拆分用例" ) else: owner[step] = idx missing = [s for s in range(1, step_count + 1) if s not in owner] if missing: problems.append(f"以下操作步骤没有对应预期结果: {missing}") return problems # 合法示例:删除执行集,1-2 走向同一结果,3 单独一个结果 assert check_step_expect_mapping(3, [ "1-2:可成功删除未挂用例的测试执行集", "3:系统提示该目录下存在用例,删除失败", ]) == [] # 非法示例:操作 1 同时落入两个预期分支,即一对多 assert check_step_expect_mapping(2, [ "1:删除成功", "1-2:删除失败", ]) != []

这段代码把"一对多禁止、多对多需编号"落成了三个可执行约束。参数说明上,step_count是从操作步骤段落里数出来的实际编号数,不是数组长度;expects里每条文本的编号前缀是唯一的解析入口,所以编号前缀一旦漏写,校验会直接报错而不是静默通过——这一点比靠人眼扫一遍靠谱得多。

实际用的时候我会再加一条:编号范围内的步骤如果语义上不相关(比如"删除一级目录"和"删除子目录"被塞进同一组预期),代码查不出来,只能靠评审。机器管格式,人管语义,这条分工线别混。

4.3 拆分还是合并:一条判定线

原文在用例划分原则里给了两个方向相反的提示:同一个需求检查点对应多种操作步骤,可合并编写一条用例,用例应详细列出所有的操作步骤;同时又说"不建议使用"多种操作对应多个预期结果的形式,尽量按预期结果分支拆分。

判定线其实只有一条:合并的前提是执行人在看到结果时,能给出唯一一个通过/失败结论。如果多个操作产生的是同一个结论(都成功、都失败、都提示同一类信息),合并;如果产生的结论不同(部分成功部分失败),拆开。

举原文里的例子,"删除执行集_含有效未执行 + 作废未执行用例"这一条,操作是分别删除有效用例目录和作废用例目录,预期是两条都删成功且用例数据都不受影响——结论唯一,可以合并。"添加测试执行集_输入有效性检查_分类名称"这一条,五个操作对应五种不同的提示信息,其中两个失败三个成功——结论不唯一。这条用例在原文里被保留为一条,但从判定线看,更稳妥的处理是拆成"名称为空/超长/重复"和"名称合法"两组。

5. 排查:用例评审里反复翻车的四类问题

5.1 前置条件写成"执行上一条用例":用例集退化成串行链

现象:一批用例单独执行时大量失败,按顺序整批跑就全过。测试报告里的通过率看着漂亮,实际毫无参考价值。

原因:前置条件写成了"先执行 XX 用例,确保存在一笔待审核订单",用例之间形成了隐式依赖。执行人为了省事跳着跑,或者中间有人改了一次数据,后续全部连锁失败。这类问题在评审时极难发现,因为每条用例单独看都写得挺完整。

解决:把前置条件从"动作"改写成"状态"。"先执行 XX 用例"改成"系统中存在一笔状态为待审核、金额 1000 元、由指定用户创建的订单"。状态可以用脚本预置、可以手工造,不依赖任何其他用例的执行结果。改完之后,用例的独立性是可验证的:任意单条用例抽出来,只按前置条件准备数据,应当能跑通。

5.2 操作步骤里夹带检查结果:执行人分不清该点还是该看

现象:一条用例执行完,执行人填了"通过",但问他是哪个检查点通过了,说不清。等生产上出了问题回头查,发现用例里那句"确认列表正确显示"从来没被真正验证过。

原因:操作步骤写成了"点击查询,确认列表显示 10 条记录并按时间倒序排列"。这句话里"点击查询"是动作,"确认列表显示"是判断,两件事挤在一句里。执行人在点完按钮的即刻就下了结论,此时异步查询可能还没返回。

解决:把操作步骤里的所有"确认""检查""验证"字样全部挪到预期结果。操作步骤只保留入口、输入要素、按钮、任务、操作顺序。改完后预期结果会变长,这是好事——变长说明检查点被显式列出来了,而不是藏在动作里。

5.3 预期结果写成"正常显示":不可判定的断言

现象:评审时所有人对这条用例都没意见,执行时每个人给出不同的结论,有人判通过有人判失败,最后靠口头讨论定调。

原因:预期结果停留在"页面正常显示""系统给出合理提示""数据正确保存"这类描述。这些描述依赖执行人的主观判断,不同人对"合理"的标准不一样,用例就失去了作为判定依据的功能。

解决:把每一层都写实。页面层写清哪些要素、什么位置、什么状态;提示层写清关键文案内容;存储层写清哪张表、哪些字段、取什么值;一致性层写清前后端数据是否一致。涉及后台系统的用例,必须加上日志输出检查。判据一旦落到字段级,执行人的主观空间就没了。

5.4 覆盖了正常流程就以为覆盖了功能:异常与边界整体缺失

现象:一个模块的用例数量不少,但跑完全部用例,生产上还是出现了"输入超长字符导致页面白屏""分页到最后一页报错"这类问题。

原因:用例设计停留在"功能正确性测试"这一种方法上——输入实际数据验证功能是否实现。异常测试、边界值测试、等价类划分这些方法没有被系统性地用起来,导致异常路径和边界值的覆盖完全靠个人经验,而经验是不可继承的。

解决:在用例编写阶段强制过一遍设计方法清单。异常测试按"模拟一个不了解产品的客户执行任意操作"的思路走一遍;边界值测试按"刚刚小于、稍小于、等于、刚刚大于、稍大于"五个点各取一组数据;等价类划分把有效和无效输入各切几类。原文里给的例子很具体:利率浮动比例的边界值是 0;前端限制长度与数据库字段长度不一致是异常测试的典型场景。清单过一遍,缺口就出来了。

6. 设计取舍:颗粒度、可维护性与自动化用例的三角平衡

颗粒度这件事没有最优解,只有平衡点。原文在划分原则里写得很坦白:颗粒度过粗会导致测试点遗漏,过细会引发维护成本高。这两句话背后是一个真实的三角——覆盖度、可维护性、执行效率,任何两个上去,第三个就得下来。

细颗粒度的代价不只是维护成本。一条用例只验证一个检查点,用例总数会翻几倍,评审时间、执行时间、回归时间同步翻倍;更麻烦的是需求变更时的连锁修改。一个字段规则改了,如果它散落在三十条用例的预期结果里,改动量就是三十处,漏改一处就是一颗定时炸弹。粗颗粒度反过来,一条用例把整个流程塞进去,改一处只改一条,但这条用例失败时你根本不知道是哪个环节坏的——这就是黑匣子。

我倾向于的处理方式是分层:流程类用例保持中等颗粒度,一条用例覆盖一条完整主流程,因为流程的价值就在于端到端串起来;功能点类和界面类用例保持细颗粒度,一个检查点一条,因为这类用例的变更频率高、复用频率也高,细粒度才能精准定位和局部替换。

第二个取舍在自动化用例和功能用例的关系上。原文的说明是:同一个功能的自动化用例和功能用例应匹配,若自动化用例不能完全覆盖功能用例,则将功能用例和自动化用例拆分成多个互补用例集。这里的关键词是"互补"——不是让自动化用例复刻功能用例,也不是让两套用例各写各的,而是明确划分各自覆盖的区间。自动化擅长的是数据驱动型的重复验证(接口入参校验、批处理的各类数据量场景),功能用例擅长的是需要人判断的界面和交互。两套用例如果大面积重叠,维护成本翻倍而覆盖度不变;如果完全不重叠又有缝隙,缝隙里就是漏测。

第三个取舍是测试需求与测试用例的层级关系。测试需求停在"检查点"这一层,用例落到"操作和判据"这一层,两层分开维护。好处是需求变更时只改需求层的检查点,用例层按需跟进;坏处是多了一层映射关系要维护。我的经验是,只要末级需求下的检查点数量超过五个,这层分离就是划算的——五个以上检查点摊在一条需求里,不做分离的话,需求描述那一格会变成一坨谁也读不下去的文字。

验证这套东西有没有效,方法比想象中朴素:拿最近三个月的生产问题,逐条反查对应用例。如果一条都查不到对应用例,说明链路在需求分析阶段就断了;如果查得到用例但用例写的是"正常显示",说明断在预期结果这一层;如果用例写得很全但没人执行,那是优先级和执行策略的问题,跟设计无关。这三种情况的修法完全不同,别混在一起改。

从那以后我每次评审用例,都会先挑三条预期结果写得最短的,问一句"这条失败了,你怎么判断它是失败了"——答不上来的,整批退回重写。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询