说起"测试用例"这四个字,圈外人很容易把它理解成一件"写文档"的活儿:需求评审完了,照着功能点把步骤列一列,填上预期结果,一个用例就算完成了。我见过不少刚入行的测试同学,一天能"写"出几十条用例,结果评审时被开发反问两句就卡住——这条用例你设计出来是想发现什么问题?需求里那个例外分支,你为什么完全没想到?之所以会这样,根本原因是把"设计测试用例"当成了"记录功能说明",而不是把它当作一次实打实的工程决策。
这篇内容我想聊透的就是"设计"这两个字。它到底在设计什么、有哪些能直接上手的方法组合、怎么从业务需求里挖出容易被漏掉的规则、一个用例该检查几项、以及现在AI能帮你做到哪一步。这套思路不只是用来交差,它决定着你最终是"测了"还是"测到位了"。无论你是刚转行的测试新人,还是做了几年却总觉得用例设计靠感觉的人,这篇都值得花十分钟看完。
1. 先想清楚:测试用例到底在"设计"什么
1.1 "写用例"和"设计用例"是两种完全不同的姿势
很多人开工第一件事,就是把PRD打开,对着功能列表一行一行翻译成用例。这个动作本身没什么大错,但它只是"覆盖了需求",并没有真正回答一个问题:这些用例合在一起,能不能用最合理的成本把缺陷拦住。
我习惯把用例设计理解成一份"抽样计划"。一个功能点的输入空间、数据状态、操作顺序排列组合起来,往往是几十万甚至几百万种可能。人力和时间有限,我们不可能全测,也不该全测。用例设计就是在这片巨大的空间里,选出最有代表性的样本,用最小代价覆盖最大的风险。
如果你始终抱着"把所有功能点都列成用例就算完成任务"的心态,那测出来的结果是可预期的:正常路径全绿,异常路径随缘。而线上出问题,恰恰绝大多数都发生在你"没想到"的地方。
1.2 用例的本质:把输入空间、环境状态和操作路径压缩成有限样本
我之前带新人时常用一个类比:体检不会把人体内所有指标都查一遍,而是根据年龄、性别、家族史挑出最关键的项目组合,用一套合理方案筛出绝大多数潜在风险。测试用例就是软件的体检套餐——它不是功能的复述,而是对"可能会出问题的地方"做的一次有条理的排查。
具体到软件测试,我们要覆盖的空间有三个维度:
- 输入空间:参数值、字段长度、类型、组合关系
- 数据状态空间:前置状态(新建、待审核、已生效、已失效)、库存余量、账户余额
- 操作路径空间:正常流程、分支流程、异常回退、重复操作、并发操作
设计用例时,每个用例都应该能回答出它在哪个空间里采样、采这个样是为了验证什么。如果一条用例连自己"为什么存在"都说不清,那这条用例多半是凑数的。
1.3 判断一套用例好不好的三个客观维度
我平时评审用例,不会只看"数量够不够",而是盯着三个维度:
| 维度 | 弱用例的表现 | 强用例的表现 |
|---|---|---|
| 有效性 | 大量用例永远通过,测完说不出新信息 | 每条用例都有明确的失败理由和风险点 |
| 效率 | 写了几百条,执行和回归成本极高 | 用几十条用例换回高缺陷发现率 |
| 可维护性 | 需求一改,用例大面积重写 | 需求变更时,只需改少量关联用例 |
有效性是最容易被忽视的。很多团队用例库动辄上千条,实际跑起来却根本发现不了缺陷,原因就是大量用例在"验证功能正常工作",而没有去"挑战功能的脆弱点"。设计用例时多问一句:"这条用例如果失败了,能说明程序哪里有问题?"问不出来的,慎重放进去。
2. 三个方法别当成模板套:等价类、边界值、场景法怎么组合
2.1 等价类划分:先学会分类,才能学会"偷懒"
等价类的基本思想不复杂:把数不清的输入数据按"程序是否用同一套逻辑处理"分成几个子集,每个子集里只取一个代表值来测。关键是这个"同一套逻辑"四个字。
我见过很多用例把用户名分成"中文、英文、数字、特殊字符"来测,这其实是按"外观"分,不是按"处理逻辑"分。如果程序里的校验正则只允许字母和数字,那么在程序眼里,"abc"和"xyz123"是同一类,你测十个"看起来不同"的合法值,效果和测一个完全一样。
正确的做法是先搞清楚程序的分支条件。比如一个注册接口,用户名长度为6到20位,包含字母数字下划线,那么有效等价类是"6到20位且字符合法",无效等价类包括"太短""太长""含非法字符""为空"。每个类里抽一个代表值即可,没必要穷举。
特别提醒:无效等价类不是随便挑几个不合理值就行,它是异常分支能否被正确触发、错误提示是否准确的关键验证。很多线上事故恰恰是因为开发没拦住一个特别"不该出现"的输入,而用例里恰好没测这个无效类。
2.2 边界值:缺陷最爱的藏身地就是临界点
边界值为什么值得单独拿出来强调?因为开发在写判断条件时,最常犯的错误就是"差一个数"。用大于还是大于等于、数组下标从0还是从1开始、日期比较按哪一天的零点算,这些边界的偏差在代码review时肉眼很难发现,但一跑用例就会现出原形。
实际操作时,我会把等价类和边界值绑在一起用。比如"密码长度为6到20位"这个需求,有效等价类是6到20位,无效等价类分别是小于6位和大于20位,那边界值就要取5、6、7和19、20、21这六个数。取5验证低于下限被拦截,取6验证下限本身合法,取20验证上限合法,取21验证超过上限被拦截,中间的7和19是正常值,用于确认边界内功能稳定。
这里还有个细节:闭区间和开区间。促销规则写"满300减50",到底订单金额刚好300能不能用优惠券?不同产品可能有不同的定义,设计用例前必须确认清楚,然后在300这个点上分别设计"刚好达标"和"差一分不达标"两条用例,两边的预期结果必须都能在需求里找到依据。
2.3 场景法:用户是按流程用产品的,不是按功能清单用的
等价类和边界值再熟练,也只能解决"单个输入正不正确"的问题。用户真实使用时,是沿着一条操作流程往前的,中间某个环节失败了,系统要能给出合理的下一步出口。场景法就是干这个的。
我常用的做法是把一个业务场景拆成三类路径:
- 主路径(基本流):用户按最顺畅的方式完成核心目标
- 备选路径(备选流):在主路径上换一种方式达成目标
- 异常路径:中途出现错误、中断、超时、重复操作时,系统怎么处理
拿"登录"来说,主路径是输入正确账号密码进入首页;备选路径可以是"忘记密码后重设再登录""第三方授权登录";异常路径包括"密码连续错误触发锁定""验证码过期""会话超时后点击登录"。
场景法最大的价值是把零散用例串成了故事,执行起来更贴近真实使用,也更容易发现"单个功能都对,但串起来就出问题"的集成缺陷。
2.4 三者怎么组合:登录模块的一次完整拆解
很多人学了一堆方法,到真正动手时依然不知道先取哪个。我的习惯是先用场景法搭骨架,再用等价类和边界值填血肉。
以一个带用户名、密码、验证码的登录接口为例:
- 先用场景法定主流程:正确凭据登录成功
- 再用场景法定分支:验证码错误、密码错误、账号锁定、找回密码后登录
- 对每个字段做等价类划分:用户名是否为空、是否含非法字符、是否存在;密码是否为空、长度是否在限制内;验证码是否正确、是否过期
- 对长度类限制取边界值:比如密码6到20位,取5/6/7/19/20/21
- 对状态类数据补充特殊值:禁用账号、未激活账号、已删除账号
这样一套下来,用例既有结构又有颗粒度。如果条件组合特别多,比如三个条件各有三种取值,组合起来27种全测太浪费,我会再引入判定表或正交试验法,挑出覆盖全部单因素和关键组合的最小集合。方法永远是为"用最少的用例发现最多问题"服务的,不是为了凑美感。
3. 拿商城下单接口练一遍完整设计流程
3.1 从PRD里挖出隐藏规则:需求文档永远不会把真相全写出来
商城接口测试用例是很多人面试和实际工作中会碰到的题目,我拿"创建订单接口"来做完整示范。单看这个接口的名字,新手往往只想到"选好商品、点提交、生成订单"这三板斧。但真实场景里,这个接口背后至少压着六条业务规则:
- 用户必须是已登录且账号状态正常的
- 商品必须处于上架状态
- 下单数量不能超过库存可售数量
- 订单金额要经过商品单价、数量、优惠券的完整计算
- 优惠券使用有门槛和有效期限制
- 同样的请求重复提交不能生成重复订单(幂等性)
这些规则里,前几条PRD会写,最后一条幂等性就经常被漏掉。可现实里用户手抖点了两下提交、或者接口超时后前端自动重试,后端如果没做幂等处理,就会产生两个订单。这种缺陷一旦上线,造成的客诉和财务对账问题非常麻烦。
3.2 把接口入参拆成字段维度表
我接到接口文档后,习惯先把入参全部列出来,逐字段标注数据类型、是否必填、长度/取值范围、业务约束。比如下单接口的入参可能是这样:
| 字段 | 类型 | 约束 | 需要重点考虑的测试点 |
|---|---|---|---|
| userId | Long | 必填,已登录用户 | 不存在、已注销、未登录 |
| skuId | Long | 必填,商品标识 | 不存在、已下架、已删除 |
| quantity | Integer | 必填,正整数 | 0、负数、超库存、超单笔上限 |
| couponId | Long | 非必填 | 不存在、已过期、不满足门槛、已使用 |
| addressId | Long | 必填,收货地址 | 不存在、地址非本用户 |
| remark | String | 非必填,限200字 | 超长、空字符串、特殊字符 |
字段拆完之后,我要单独做一张"字段-方法对应表",把等价类、边界值、异常值贴到每个字段上,避免遗漏。这张表不用太复杂,但它是后续生成用例清单的底稿。
3.3 业务规则转用例:库存和幂等是重头戏
字段级别的用例只能防"参数异常",真正体现设计水平的是把业务规则翻译成用例。
以库存为例,假设某SKU当前可售库存是10件,下单数量的测试用例至少要有这几条:
- 购买1件,正常成功,库存变9
- 购买10件,刚好等于库存,成功
- 购买11件,超库存,提示库存不足并拦截下单
- 并发下同时购买10件和1件,验证不会超卖
幂等性这边,我会准备一个固定的请求体,在第一遍发送成功后,用完全相同的请求体再发一次。预期结果是第二次请求返回"订单已存在"或者直接返回第一次的订单号,数据库中订单表只有一条记录。这个用例我建议放在P0优先级,因为它直接关系资金安全。
优惠券门槛也是典型的边界值场景。规定"满100元减20元",就要测订单金额正好100元、99.99元、100.01元三档,分别验证优惠券是否可用、最终实付金额是否正确。99元和100元的差别,恰恰是用户最容易投诉、开发最容易用浮点数精度算出问题的地方。
3.4 一套可直接参考的下单接口用例清单
为了更直观,我按一个简化场景给出一组可落地的用例清单:SKU A单价50元,库存10件,用户有一张"满100减20"的优惠券,收货地址已配置。这里列出核心用例:
| 用例编号 | 用例描述 | 优先级 | 前置条件 | 操作步骤要点 | 预期结果 | | --- | --- | --- | --- | --- | | TC-01 | 正常下单2件 | P0 | 库存10件 | 用优惠券下单2件 | 下单成功,生成订单,金额80元,库存余8 | | TC-02 | 优惠券门槛临界 | P0 | 库存10件 | 购买2件,金额恰好100 | 优惠券可用,实付80元 | | TC-03 | 门槛差一分 | P1 | 库存10件 | 购买1件,金额50 | 优惠券不可用,实付50元 | | TC-04 | 库存刚好临界 | P0 | 库存10件 | 下单10件 | 下单成功,库存归零 | | TC-05 | 超库存拦截 | P0 | 库存10件 | 下单11件 | 返回库存不足,不创建订单 | | TC-06 | 重复提交幂等 | P0 | 库存足够 | 同一请求体发送两次 | 第二次提示重复,订单仅一条 | | TC-07 | 非法数量 | P1 | 库存足够 | quantity传0或负数 | 参数校验报错,不创建订单 | | TC-08 | SKU不存在 | P1 | 无 | skuId传随机不存在值 | 返回商品不存在,不创建订单 | | TC-09 | 商品已下架 | P1 | 商品下架 | 对下架SKU下单 | 返回不可购买,不创建订单 | | TC-10 | 优惠券已使用 | P1 | 券已核销 | 用已用券下单 | 返回券不可用,不创建订单 | | TC-11 | 未登录调用 | P1 | 无登录态 | 不带token调用下单 | 返回未授权,不创建订单 | | TC-12 | 备注超长 | P2 | 库存足够 | remark传201个字符 | 返回参数校验错误 |
注意,这套用例里我刻意把"库存不足""重复提交""优惠券门槛"放到P0,因为这三类问题一旦出线上事故,影响的是钱和信任,优先级必须最高。
3.5 断言设计:怎么判断一条用例到底"过"还是"没过"
接口测试里最常见的断言失误,是只看返回里的"success"字段。我踩过这类线,返回成功但订单实际没建上的情况真实存在。现在我做断言至少分三层:
- 第一层:响应断言。检查HTTP状态码、业务码、返回体里的订单ID、金额等关键字段。
- 第二层:数据断言。查库确认订单表真实插入了记录,库存表扣减数量正确,优惠券状态从"未使用"变为"已使用"。
- 第三层:下游状态断言。如果下单后要发消息或写流水,需要确认消息已投递、流水已落库。
一句话总结:下单接口的预期结果不是"下单成功",而是"订单、库存、优惠券、流水四方数据全部一致"。把预期结果写细一点,执行时才能一眼看出到底哪里不对。
4. 一个用例最多检查几项?别在这个问题上内耗
4.1 "一个用例只验证一件事"这句话得分场景听
在测试社区里流传很广的一个说法是"一条用例只能有一个断言"。这句话本身没有错,但很多人在接口测试、端到端测试里也机械执行,结果用例数量爆炸,维护成本高到团队想哭。
我的理解是,这句话主要适用于单元测试和接口测试中的"最小失败定位"场景。一个单元函数,当然希望一个用例只验证一个表现,失败了能立刻定位到是哪行代码出的问题。但到了端到端场景,比如"用户完成下单并支付成功",这一个用例本身就要经历多点校验:订单金额对不对、支付状态有没有更新、优惠券有没有核销。硬拆成三个用例,反而破坏了业务完整性,前置条件和数据准备都要重复做三遍。
4.2 用例粒度过细和过粗,分别是两种灾难
用例拆太细,最直接的后果是数量膨胀。一个登录功能拆出五十条用例,执行十分钟,维护两小时,因为前端文案改一个字,所有引用这个文案的用例预期结果都要跟着改。更麻烦的是,很多细粒度用例之间共用了公共步骤,一旦前置步骤失败,后面一串用例全部报障,排查时还得从第一条开始看,效率极低。
用例写太粗,问题同样严重。预期结果里写一句"页面正常展示",执行时看到页面乱码都说不清这算不算失败;失败后也找不到是哪个环节出的问题,只能重新手工复跑一遍去定位。这种用例只比没有稍好那么一点。
4.3 我判断一条用例是否需要拆分的三个信号
我平时不会去死记"最多检查几项",而是靠三个信号来决策:
信号一:预期结果里的独立检查点超过4个。如果一条用例的预期结果列了五六条,而且这些检查点分属不同的模块或系统,那就拆。比如"下单成功、库存减、券核销、消息发送"这四点属于四个层面,可以拆成一条接口结果用例、一条数据一致性用例。
信号二:用例存在多个前置分支。比如"如果用户是新用户则走A逻辑,如果是老用户则走B逻辑",这种时候直接拆成两条独立用例,因为执行路径完全不同,合成一条只会让失败时的信息变得含混。
信号三:执行失败时无法快速定位。你可以自问一句:这条用例红了,我能在半分钟内说出大概卡在哪个环节吗?说不出来,就是太粗了。反过来,如果一条用例只是断言点多,但都集中在同一个业务闭环里,合并着写完全没问题。
4.4 落到团队里的执行建议
结合这几年的实操,我现在的原则是:单元测试和接口测试,倾向一个用例一个主检查点,把定位成本降到最低;端到端业务场景,允许一条用例包含三到五个检查点,但必须保证这些检查点同属一条主流程,且每个检查点都有明确的数据可验证。
我还会在用例模板里加一列"验证目的",一句话说明这条用例到底想发现什么问题。这一列看起来不起眼,但在用例评审时非常有用——评审员一眼就能看出哪些用例是凑数的,哪些用例是真正有风险针对性的。如果你所在团队还在用"条数"考核测试工作量,我建议尽早把指标换成"高风险覆盖数"和"缺陷发现数",这样用例设计才会往高质量方向走。
5. AI能帮你写用例,但设计决策还得自己拍板
5.1 现在的AI写测试用例,到底靠不靠谱
"AI根据PRD生成测试用例"这个词最近热得很,我也在团队里实际试过几轮。结论是:AI完全能用,但智商取决于你喂它的信息质量和期望值管理。
把一份结构完整的PRD和接口字段说明贴给AI,它能很快产出一版覆盖正常路径、常见边界、基础异常场景的用例表格,格式规整,命名也规范。对于新人或者刚接手的模块,这个初稿能省掉两三个小时的机械劳动,非常值。但如果指望AI看完一段模糊的需求描述,就能自动挖出"重复提交会创建两个订单"这种隐患,那还不现实。它不了解你们系统的历史缺陷,也不了解业务上的潜在资金风险。
坦诚地说,AI现在更像一个"非常勤奋但缺乏经验的实习生"。它能帮你把框架撑起来,但哪里要加权重风险用例、哪条业务规则和另一条规则之间存在隐性冲突,这些判断还是要人来定。
5.2 我实测好用的AI生成用例Prompt写法
很多人用AI生成用例效果差,问题大多出在提问方式上。直接甩一句"帮我写测试用例",得到的当然是一堆正确的废话。我常用的套路是把需求上下文、字段定义、输出要求拆开喂给它。
下面是我实测过几轮、产出质量比较稳定的Prompt模板,你可以直接抄走:
你是一名资深测试工程师,请根据以下需求设计测试用例。 【需求描述】 (这里粘贴PRD中对该功能的描述) 【接口定义】 (粘贴接口文档中的入参字段、类型、约束、返回码说明) 【补充说明】 1. 库存为10件,优惠券满100减20,要求并发和幂等场景必须覆盖 2. 用户未登录、商品下架、优惠券已使用等异常场景必须覆盖 【输出要求】 1. 用Markdown表格输出:用例编号、用例描述、优先级、前置条件、操作步骤、预期结果 2. 每条用例请标注使用的设计方法(等价类/边界值/场景法/错误推测) 3. 优先输出P0高风险用例,再补充P1/P2用这个模板生成完之后,我会把返回的表格复制到用例管理工具里,然后做两件事:一是逐条审查预期结果,看有没有含糊的"正常返回""显示正确"这类表述;二是打开自己的历史缺陷库,把最近半年在这个模块上踩过的坑对照一遍,缺的用例补上。
5.3 哪些环节AI做到不到位:经验和技术债是最后一道防线
我试过的AI模型里,普遍薄弱的环节有三个:
- 业务约束推导。比如"优惠券不能和秒杀活动叠加""白名单用户才能看到这个商品",这类需要结合业务上下文才能推导出的规则,AI经常漏。
- 历史缺陷模式。你们这个系统曾经因为浮点数精度、时区转换、字符集出过什么事故,AI完全不知道。它生成的用例里自然不会针对这些"前科"做特判。
- 跨系统数据流转。下单涉及订单、库存、优惠券、支付、物流多个系统,AI往往只盯着当前接口,忽略了数据一致性的检查项。
所以我现在的定位很明确:AI出初稿,我做设计决策,最后再用反向问题验收,比如拿生成的用例去逐条反问"缺陷是什么?",答不上来的就删。这个流程走顺之后,用例设计速度大约能提升三到四成,质量不降反升。
5.4 用例工程化:从"写用例"到"用例即资产"
顺着AI出现,行业里"harness工程化"这个词被频繁提起。这类工具能做的事包括自动加载用例定义、生成接口测试脚本、跑完自动产出报告,甚至把代码变更和用例执行关联起来,再做一轮自动Review。本质上,测试用例正在从一份给人看的文档,变成一套可被机器执行的资产。
这意味着用例的写法也要同步变化:字段要结构化,步骤要能还原成可调用的数据,预期结果要能对应到具体的断言表达式。AI生成用例之所以有价值,也正是因为它天然倾向结构化输出,可以直接喂给harness用。
但不管工具链怎么升级,最初"用例设计"的决策环节——选哪些场景、按什么优先级、如何权衡投入产出——依然是最值钱的部分。工具可以帮你把用例跑起来,但跑什么、为什么跑,得你说了算。
5.5 我现在的完整实操流程,供你参考
最后分享一下我目前在团队里用的流程,不见得多高级,但每一步都有明确产出:
- 需求拆解:把PRD和接口文档过一遍,列出所有业务规则和字段约束
- AI初稿:用上面的Prompt模板生成首版用例,作为草稿底稿
- 人工评审:对着历史缺陷库和业务经验,补重点风险用例,删掉无意义用例
- 结构化入库:把用例字段整理成可导入管理工具的格式,确保能被后续工程化利用
- 执行复盘:每轮测试结束后,把新发现的缺陷补进用例库,并反向标注它是用哪种方法挖出来的,持续积累团队的设计经验
这几步做完,用例库才不是一潭死水,而是越用越懂这个系统的活资产。
设计测试用例这件事,越往后做越能体会到,它考验的根本不是"会不会用方法",而是"有没有判断力"。方法学三天就会,判断力要靠一次次踩坑、复盘、再试验才能沉淀下来。我到现在还保留着一个习惯:拿到新需求时,先不急着列用例,而是先单独写一句话——"这个需求最可能在哪个环节出问题",然后才开始设计。你也不妨试一次,大概率会发现,顺着这句话展开的用例,比照着PRD平铺出来的用例有用得多。