资讯动态

从设计思维到落地实践:测试用例设计的经典方法与创新探索

发布时间:2026/9/8 5:21:11 来源:尧图企业网站定制
有一次线上事故开发同事只改了三行代码就修好了PR描述里只写了半句话漏了订单取消状态的边界判断。但测试组围在会议室里复盘到下班真正扎心的不是开发漏写判断而是这条测试用例从设计文档到用例库压根就没有出现过。同一类问题已经不是第一次发生了用例几千上万条覆盖率报告全绿可线上故障永远来自那些“没想到”的路径。这让我越来越确信一句话测试用例不是写出来的是被设计出来的。写了多少条不重要重要的是这些用例是怎么被设计出来的、依据是什么、覆盖的是不是真正有风险的行为。很多测试新人甚至部分老手一上来就对着需求文档逐条列用例列完了就执行、就提交完全没有“设计”这一步。这篇文章我想把我这些年做测试用例设计的思路完整整理一遍分经典方法和创新方法两条线来聊。经典方法不是过时是很多人在错误地使用创新方法也不是噱头用好了能补齐经典方法的盲区。不管你是刚入行的测试新人还是想系统优化用例设计流程的QA负责人这篇文章应该都能给你一些可落地的参考。1. 用例不是“写出来”的是被“设计”出来的1.1 需求到用例之间的那道隐形鸿沟很多团队的需求文档写得很模糊。拿到一句“用户可以对订单申请取消”不同的人会写出完全不同的用例。有人写“点击取消按钮订单取消成功”就结束了有人会拆成取消申请提交、取消条件校验、取消状态推送、取消后库存回补、取消后优惠券返还、渠道通知联动等十几条。差距不是工作态度问题而是测试设计的思维方式问题。需求描述的是业务意图用例描述的是系统行为。从“业务意图”到“系统行为”之间隔着一个关键动作把需求翻译成可验证的输入条件、前置状态、执行步骤、预期结果和隐含约束。那家伙“漏了订单取消状态的边界判断”本质上是需求里“订单在什么状态下可以取消什么状态下不能取消”这个隐含规则没有被翻译到用例里。所以在设计用例之前先问自己五个问题这个功能真正要解决的用户问题是什么系统当前处于哪些状态时这个功能是可达的哪些输入组合是合法的哪些是非法但可能发生的失败路径和异常路径上用户会看到什么、系统会记录什么这个功能和周边模块有哪些联动关系这些问题过一遍你自然会发现写用例只是最后一步的文字化动作真正的功夫在设计前的分析。1.2 测试设计的三个底层思维分解、状态、风险我习惯把测试设计思维浓缩成三个词分解、状态、风险。分解思维对应的是把复杂系统切成可以单独验证的单元。一个“提交订单”动作可以分解成地址校验、商品库存扣减、优惠计算、支付通道选择、订单生成、消息通知几个环节。每个环节的输入输出相对独立这样更容易定位问题和设计用例。没有分解思维你对一个大功能只能写出“能成功”和“会失败”两条用例但有了分解你就能在每一层找到边界和分支。状态思维要求你关注数据对象在生命周期里的迁移过程。订单有草稿、待支付、已支付、已发货、已完成、已取消等状态每个状态下允许的操作集合完全不同。状态思维能帮你设计出状态转换类用例这类用例最容易被“对着需求逐条读”的方式漏掉。风险思维解决的是“测什么都测不穷”的问题。任何系统的输入空间都是无限的你不可能穷举所有可能性。测试设计的本质是用有限的用例去覆盖那些一旦出错代价最大、发生概率最高的行为。P0用例保支付、保安全、保核心链路P1覆盖主要业务分支P2再考虑体验和边缘场景。把所有用例写得一样重等于没有重点。1.3 从缺陷反推设计优先级我之前在团队里做过一个统计把过去半年的线上缺陷拿来反向标注看它们落在用例设计的哪个维度。结果很有意思约40%的缺陷来自“状态转换”场景没覆盖30%来自“非法输入和异常路径”处理不当只有不到20%来自正常主流程剩下的是兼容性、数据一致性这类跨模块问题。这就很能说明问题。很多团队的用例库看起来庞大但大量用例集中在正常主路径上把“用户按标准方式操作程序”测了一遍又一遍真正有杀伤力的异常路径、状态切换、外部依赖故障反而没人设计。所以我后来定了条规矩每个功能模块的用例结构里正常路径用例占比不许超过50%剩下的必须分配给异常容错、状态边界和外部依赖场景。这条规矩本身也是测试设计只不过设计对象从用例变成了用例的结构。2. 经典方法各有脾气用对场景才是经典2.1 等价类和边界值不是简单地“把数据分段”等价类划分是入门第一课但大多数人没真正用好。等价类划分的核心思想是如果一组输入对程序的行为产生同样效果那它们属于同一个等价类从中取一个代表值测试即可。难点在于判断“同样效果”的标准。比如支付金额字段流程上数值型校验整数、范围、业务型校验余额是否足够、规则型校验是否满足满减门槛分属不同维度每个维度都该有自己的等价类不能笼统地分成“有效金额”和“无效金额”两类。边界值分析又经常和等价类混在一起。我见过不少用例设计写了“最小金额1元、最大金额10000元”就完事了完全没有处理开闭区间的问题。金额大于0且不超过10000边界值除了1和10000还要考虑0、0.01、9999.99、10000.01、负数这些点。如果接口设计用(0, 10000]那0本身就是个需要重点验证的值。这里的原则是每个边界都要测临界点两侧的值同时明确边界是开区间还是闭区间。还有一类很容易漏的边界是“长度边界”之外的“数据状态边界”。比如手机号字段除了长度11位还要考虑空字符串、全角数字、带国家码、重复提交、前后空格。这些不是长度边界而是数据形态和重复状态边界。建议设计用例时把边界值扩展到四类数值边界、长度边界、格式边界、状态边界每个字段都按这四类过一遍漏测的概率会明显下降。2.2 判定表和因果图复杂业务规则的显式化判定表是处理复杂业务规则最趁手的工具。我做过一个民宿平台退改规则的需求是否免费取消取决于预约状态、距离入住的时长、取消发起方、是否有特殊约定四个条件的组合。如果对着需求文档凭感觉写用例很容易漏掉某几条组合。判定表的结构很简单左边是条件桩和条件项右边是动作桩和动作项每一列代表一条规则。四个条件每个条件大致两个取值理论上16条规则但实际业务里很多组合是不存在或者被合并的。把真实组合逐一列出来再把动作填进去漏测组合还是一眼就能看出来。因果图是判定表的前置分析工具画出条件和结果之间的与、或、非关系再转换成判定表。说实话现在项目迭代节奏快已经很少有人在正式文档里画完整的因果图了但它的思想没有过时先梳理条件之间的依赖关系再生成组合。我现在的习惯是直接在表格里列条件和动作用“-”表示不关心项来合并规则效果和因果图等价但效率高得多。判定表真正发挥作用的前提是业务规则要问透宁可多问一句“这个条件还能拆吗”也不要带着模糊规则进入用例设计。2.3 状态转换测试状态机不是开发者的专属很多测试人员觉得状态机是开发设计阶段的东西跟测试无关这是很大的误解。订单、支付、任务、审批流这类强状态业务是最容易出线上事故的领域而状态转换测试恰恰是设计这类用例最有效的方法。做法很简单把系统对象的状态和事件梳理出来画成一张状态转换表。拿订单举例状态集合可能有待支付、处理中、已完成、已取消、退款中。事件有支付成功、支付超时、取消申请、审核通过、退款完成。然后逐条验证每个状态下哪些事件是允许的哪些是非法的。我最常用的是状态转换树的方法从初始状态出发每接收一个事件进入下一个状态分叉出所有合法路径和非法路径再挑出业务上最高频、资金风险最大的路径做重点覆盖。状态转换用例的价值在于它能回答两个经典问题这个状态能不能进来这个状态能不能出去。大多数线上缺陷都出在“不该进来的进来了”或者“该出去的没出去”。支付回调重复、取消单又被支付成功、退款完成订单还能被取消说白了都是状态转换设计不完整的问题。测试人员如果能把每个核心对象的状态转换表维护好测试设计的层次会完全不一样。2.4 正交与配对组合当组合数量失控时当输入条件有七八个每个条件又有多个取值时笛卡尔积式组合会爆炸。比如搜索民宿的过滤条件城市5个、入住日期4个、房型3个、价格档位4个、是否含早餐2个、排序方式3个理论上组合数是1440个系统测试根本不可能全测。这时候就该用配对组合测试pairwise的思路大多数缺陷由单个参数或两个参数的交互触发涉及三个及以上参数交互的缺陷占比很低。所以只需要保证任意两个参数的所有取值组合至少出现一次就能用很少的用例获得极高的组合覆盖率。微软的PICT工具是这领域最轻量的选择写一个模型文件就能生成配对组合用例集。Platform: x86, ARM, MIPS OS: Win10, Linux, macOS Browser: Chrome, Firefox, Edge IF [Platform] ARM THEN [OS] Win10;上面是PICT模型的一个例子。三行参数定义加一行约束运行后能生成一组几十条的用例覆盖所有两两组合。这类方法特别适合配置兼容性测试、筛选条件组合测试。但它也有明显边界它保证的是参数组合覆盖率不能替代等价类和边界值也不理解业务规则。组合测试和规则测试是两码事设计用例时不要把二者混为一谈。2.5 经典方法适用场景速查方法主要解决什么问题典型适用场景常见误用等价类划分同类输入行为一致输入校验、字段格式只分有效类忽略无效类边界值分析临界值附近的缺陷数值范围、长度限制忽略开闭区间和状态边界判定表多条件组合决策业务规则、退改规则、审批流条件没问透就列表状态转换测试状态迁移合法性订单、支付、任务流只测正常状态流正交/配对组合组合爆炸配置兼容、过滤组合忽略业务约束盲目套用例场景法用户真实使用路径端到端流程、主流程回归把场景法当用例罗列3. 创新方法探索式、模型驱动与AI辅助的落地笔记3.1 探索式测试先有好的“章程”再谈自由探索式测试被很多人误解成“不写用例随便点点”这恰恰是它最容易翻车的地方。真正的探索式测试同样是设计出来的只不过设计的东西是一个带有明确目标和启发式线索的“章程”Charter而不是一条条写死的步骤。一个好的探索式测试章程长这样“以一个新注册用户的身份探索支付成功页在支付成功回调延迟的情况下调查页面状态与订单状态的一致性。”这句话包含了角色、区域、风险点和调查目标四个要素。每个探索式会话控制在60-90分钟这段时间里你可以自由地在目标区域内尝试各种操作但脑子里始终绷着那根弦我在验证什么假设、哪里可能出错、我看到了什么反常现象。我经常配合使用的启发式工具包括SFDPOT从结构、功能、数据、平台、操作、时间六个维度提问还有旅行者模式把自己想象成不同目的的旅行者去逛一个软件做“地图旅行者”关心导航和链接做“游客”关心首次体验和帮助信息做“收藏家”关心收藏、历史记录这些数据保留功能。这些听起来很随意实际背后都是测试设计思维只是把设计对象从用例变成了任务和提问。3.2 基于模型的测试设计从状态图到用例生成的自动化基于模型的测试MBT是近几年越来越受关注的方向核心思路是用形式化模型描述被测系统的行为然后通过工具自动生成测试用例。对于状态复杂、长周期的业务系统手写状态转换用例容易遗漏且维护成本高MBT能把这个过程自动化。最简单的落地形态是建立文本化的状态转换模型状态待支付、已确认、已入住、已退房、已取消 事件 待支付 --支付成功- 已确认 待支付 --支付超时- 已取消 已确认 --申请取消- 已取消 已确认 --入住打卡- 已入住 已入住 --退房打卡- 已退房有了这个模型再借助工具设置起始状态、覆盖标准和路径生成规则就能自动导出测试路径和用例步骤。GraphWalker就是这类工具中比较成熟的一个支持从有限状态机模型生成满足指定覆盖准则的路径序列。MBT最大的优势是模型可以复用需求改了更新模型后重新生成用例比手改几十条用例高效得多。最大的成本也是模型建模需要投入时间模型颗粒度粗细直接决定生成用例的价值太粗覆盖不到实质逻辑太细维护成本接近重写。所以我的建议是MBT只用于状态密集型、生命周期长、规则变动频繁的核心业务对象简单CRUD功能完全没必要动用它。3.3 属性测试与生成式测试用代码生成用例属性测试Property-Based Testing的思路和传统用例完全相反。传统用例先定输入、再定预期输出属性测试是你描述一段程序在任何输入下都应该保持的“属性”然后由工具自动生成大量随机边界输入来验证这些属性。用Python的Hypothesis库举个例子from hypothesis import given, strategies as st given(st.lists(st.integers())) def test_sort_length_and_content(xs): ys sorted(xs) # 排序后长度不变 assert len(ys) len(xs) # 排序后元素集合不变 assert sorted(ys) ys # 排序结果单调不减 assert all(ys[i] ys[i1] for i in range(len(ys)-1))这个测试用例没有写死一个输入但Hypothesis会自动生成包括空列表、单元素列表、含重复元素的列表、含极端整数的列表在内的大量测试输入比手写两三组硬编码数据覆盖广得多。属性测试特别适合算法逻辑、日期解析、序列化转换、数据聚合这类输入空间大但属性明确的场景。它的局限也很明显你得能定义出“属性”如果连正确的行为都无法形式化描述属性测试也无从下手。3.4 AI辅助生成用例生成不等于设计我身边越来越多的团队开始让AI辅助生成测试用例初稿。说实话用好的前提是端正心态AI擅长从已有需求文本里抽取功能点生成格式规范、结构完整的用例草案但它不擅长识别隐含业务规则、组织约束和异常状态。举个例子我拿一段“入住前24小时免费取消24小时内取消需收取首晚房费50%”的需求让AI生成用例它通常会生成24小时整点、24小时前后一小时这类时间边界用例正确率不错。但如果需求里隐含“仅限信用分600以上的用户可免费取消”这样的跨模块规则AI基本无法从当前需求文档中推断出来。所以AI辅助的正确姿势是把LLM当一个大号模板生成器加启发式提问器来用生成的用例必须经过一个有经验的测试人员做规则校对和优先级调整。我常用的Prompt模板是这样的请为以下需求设计测试用例按等价类、边界值、场景法组织并标注优先级。 需求民宿订单支持入住前24小时免费取消24小时以内取消需收取首晚房费50%的违约金 取消后房态释放、优惠券按原有效期返还。 额外约束仅限信用分不低于600的注册用户。AI生成后我会追问三类问题异常分支覆盖了吗状态转换覆盖了吗和其他规则的组合覆盖了吗把这三问纳入流程AI生成的用例才能真正进入用例库。3.5 思维导图驱动用例脑暴让设计过程可视化思维导图不是测试理论书里的正式方法但它是测试设计过程中可视化程度最高的工具。我现在做大型需求时第一件事不是打开Excel写用例而是打开思维导图把中心主题设为测试目标一级分支按功能模块拆二级分支写测试场景三级分支补测试数据和预期结果。比如设计“优惠券”模块的用例中心是“优惠券全链路验证”一级分支有领券、用券、退券、过期处理、风控限制每个分支再往下展开。画图过程中能直观看到哪些分支特别粗壮、哪些分支几乎没展开粗壮的可能需要继续拆分没展开的要警惕是不是遗漏。导图还能方便地拖着节点走把同类的场景归到一起比在表格里来回挪行高效太多。导图做完之后我才会把它翻译成结构化的用例列表。很多人反过来一上来就在用例管理工具里逐条填写结果写了一半发现场景分类有问题又得整体返工。思维导图承担的是设计阶段用例管理工具承担的是沉淀阶段顺序不要颠倒。4. 一次完整项目的用例设计复盘民宿预订的支付与取消4.1 项目背景和测试目标去年我们做一个民宿预订平台的订单中心迭代涉及需求包括提交订单、支付超时处理、入住前取消、商家拒绝订单、退款原路返回、优惠券核销。这个迭代涉及资金流转和房态库存是整个平台风险最高的模块测试目标定得很具体不能出现用户钱被扣了房没订上也不能出现订单取消了房态还没释放更不能出现退款金额算错。整体测试策略采用“经典方法打底加探索式补测”的组合核心规则的判断逻辑用等价类和判定表覆盖订单生命周期用状态转换表覆盖端到端用户旅程用场景法覆盖最后再由两个有经验的测试成员做探索式会话查漏补缺。4.2 用例分层和经典方法落位我把用例分成六类功能路径、规则分支、异常容错、数据边界、状态转换、端到端场景。每一类对应不同的设计方法。支付金额相关字段用等价类和边界值支付金额的合法区间、余额精确到分、超过单笔限额、余额不足、并发下单导致库存不足这些用例的目标是验证“钱”相关的判断逻辑是否严格。取消规则用判定表设计取消发起方用户/商家/平台、距入住时间大于24小时/小于24小时/已入住、支付状态已支付/未支付、是否有违约金四个条件组合出真实业务里所有允许的取消路径和动作。订单状态用状态转换表从待支付到已确认到已入住到已退房到已取消每条合法转换要测非法转换更要测比如已取消订单不能再次支付成功、退款完成之后不能再次发起取消。端到端场景则站在用户视角设计用户浏览房源、提交订单、支付成功、收到确认、入住体验、退房结算、评价全链路跑通。场景法在这里的作用不是覆盖全部分支而是确保主流程在真实依赖链路上是完整的。4.3 用例评审时发现的问题这一轮用例设计暴露出很多问题我觉得很值得写出来因为都是常见陷阱。第一版用例里支付环节只设计了支付成功和支付失败两个分支完全没有“支付超时后回调才到达”的场景。实际系统中用户可能已经关掉了支付页面但支付网关的异步回调延迟到达这时候订单到底应该入账还是取消是个必须明确的状态转换问题。评审时讨论了很久规则最终确认支付超时设置15分钟超时后订单关闭并释放房态但晚到的支付回调要进入人工处理队列不能直接入账也不能直接退钱。第二个问题出在优惠券上。取消订单后优惠券的返还规则用例里写的是“订单取消后优惠券退回”但没定义退回后的有效期。评审时问了一句如果这张券在取消前就已经过期了还要不要退这个边界问题不解决上线后必然产生客诉。最终确认优惠券按原有效期返还过期不补。第三个问题是异常数据的兼容性。老订单数据里有历史遗留的脏数据比如状态是“待支付”但支付单已成功这类数据在迁移和查询展示中怎么处理。开发一开始说“历史数据不处理”但测试坚持把这些场景列入用例因为用户肯定能搜到这些历史订单。最后调整了兼容方案。这些评审场景说明一个道理测试用例设计做得好不好很大程度上取决于有没有把“语义边界”问到底而不仅是照着需求文档转述。4.4 执行结果和经验沉淀最终这轮迭代设计出约280条核心用例比需求初评时预计的少了近三分之一但缺陷漏测率反而比之前类似迭代低。执行过程中最意外的是探索式会话发现了两个用例库没覆盖的问题一个是iOS端在弱网环境下重复点击支付按钮会发起两笔支付单一个是房态释放接口在极端并发下偶发库存覆盖。这两个问题都不在业务规则内靠的是探索时对异常场景的敏感度。事后复盘团队得出一条经验经典方法负责把规则和状态覆盖做扎实创新方法负责找那些规则之外的“没想到”。两者不是替代关系而是分工关系。这个认知后来写进了团队的测试设计规范。5. 用例质量的度量与持续改进5.1 覆盖率指标要怎么看才真正有用度量用例质量最常用的指标是覆盖率但覆盖率这东西很容易自我欺骗。需求覆盖率解决的是“需求有没有被用例链接到”它只能证明每条需求至少对应一条用例证明不了质量和深度。语句覆盖和分支覆盖属于代码级覆盖率直接反映的是代码执行路径的覆盖情况但也存在一个迷惑性很强的问题即使代码覆盖率很高如果开发实现本身和真实业务预期不一致覆盖再充分也是在验证错误的代码行为。我更建议团队关注的是一组组合指标需求覆盖率加分支覆盖率加缺陷逃逸率。缺陷逃逸率指的是线上缺陷里有多少可以在用例库中找到对应用例来防止。如果一个模块的用例库看起来很饱满但线上缺陷仍不断出现说明用例设计方向和真实风险错位了。另外一个简单却容易忽略的指标是“每条用例的缺陷发现数”。统计一段时间里哪些用例真正发现了缺陷、哪些用例从创建以来从未失败过后者很可能是无效用例或冗余用例。清理无效用例和补齐高风险用例同等重要。5.2 用例评审和“死用例”治理用例不是写完就完事的资产它会腐化。一套用例库在使用一年后通常都会出现这些问题部分用例引用的字段和按钮已经变更但预期结果没更新自动化用例脚本断言写得含糊红绿失去了判断意义还有一些用例描述模糊到只有原作者能看懂人一走用例就作废。我建议每两个迭代做一次用例库迷你评审重点是找四类“死用例”描述过期、步骤不可执行、断言无效、与更高优先级用例重复。评审方法很粗暴从用例库里随机抽20%的用例请一个没参与编写的人照着步骤走一遍走不通的直接标记清理。这个做法实战效果很好成本不高但能让用例库一直处于可执行状态。检查维度典型问题处理动作可理解性步骤描述模糊依赖隐性知识补充前置条件重写模糊步骤可执行性页面元素已变更步骤无法复现更新定位信息和操作路径可追溯性找不到对应需求和业务规则补充需求链接或业务依据独立性用例执行依赖其他用例顺序拆分或补足前置数据构造唯一价值与其他用例覆盖范围高度重复合并或删除冗余用例预期有效性断言过宽或过旧红绿失真重审预期结果收紧断言5.3 把用例资产变成团队的业务地图当用例库被认真设计、持续维护之后它就不只是一份验证清单而是一张团队独有的业务地图。新人入职之后要想快速理解核心业务流程与其翻需求文档和产品原型不如直接看用例库哪些路径是最核心的主链路哪些地方最容易出异常状态是怎么流转的边界在哪里。我带过的每一个团队我都会鼓励测试成员把用例设计过程中发现的业务歧义记录下来集成到用例备注里。这些歧义是需求文档里永远不会写的知识资产。我自己也保留了一份“漏测笔记”每出现一条线上缺陷就记录缺陷背后的测试设计缺环是状态树没画全还是判定表条件没问透还是探索会话时间不够。翻过几轮之后会发现自己踩过的坑会越来越趋同而设计用例时的敏感度会越来越高。测试用例设计能力没有速成路径就是周而复始地用经典方法打底、用创新方法补漏、用度量指标修正方向然后从每一条被漏掉的用例里捡回来一点点经验。这些经验攒到一定厚度你对一个系统的直觉就是最值钱的那套用例设计方法。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价