
前两天团队评审登录模块的测试用例新来的同学一口气写了十条我粗略扫了一眼六条都在验证正确账号密码能登录剩下的四条分别改了改用户名格式和密码长度。边界情况一条没有异常场景全靠猜更别提什么条件组合覆盖。这种场景我见得太多了。测试用例这东西看起来门槛极低——无非是步骤加预期结果但真正能写好的人并不多。很多刚入行的测试同学把它当成任务流水线提测了照着需求文档拆几条写完了事。可等到回归测试漏了一个关键场景、线上出了问题复盘时发现用例库一片空白才会意识到用例设计才是软件测试里最吃功夫、也最容易被低估的环节。这篇文章把我这些年做测试积累的用例设计经验系统梳理一遍围绕标题里的四个核心问题展开测试用例到底能带来什么好处七种设计方法分别怎么用、适合什么场景粒度怎么把握才不算浪费以及拿什么标准评价一套用例写得好不好。不管你是刚入门想建立完整认知还是已经写了一阵子用例想找找自己的盲区这篇都值得看完。1. 为什么非写不可测试用例在项目里的三个硬道理先说一个反直觉的结论测试用例不是写给执行者看的至少不只是。它是整个测试过程里唯一能沉淀下来的资产。代码会重构需求会变更人来人往但一套维护良好的用例库能长期跟着项目走。很多团队不重视用例本质上是没想明白它到底解决了什么问题。1.1 它把拍脑袋测试变成了可规划的执行清单没有用例的时候测试靠什么靠脑子。但人脑的容量和稳定性都靠不住——连续测了两天功能之后你自己都记不清哪个模块测过、哪个场景漏了。而且不同的人测试风格差异极大同样一个登录功能有人能想到密码错误五次锁定有人只测了正确路径。用例解决了这个问题它把我知道该怎么测这种隐性知识转成了显性的、可跟踪的执行清单。有了这份清单测试不再是随机游走而是按图索骥。每条用例有编号、有优先级、有预期结果执行完打勾没执行的一目了然。测试进度可量化了漏测的比例会大幅下降。我在实际项目里的体会是用例还有一个隐藏作用它逼着你思考。写用例的过程本身就是一次对需求的深度梳理。很多需求问题——比如用户名长度到底限制是多少这个字段允许为空吗并发点击会发生什么——都是在写用例的时候暴露出来的。这些问题如果等测试执行时才发现往往已经晚了开发和产品都在等你的反馈效率非常低。1.2 回归测试时它是整个团队的底气软件测试里最磨人的工作是什么我投回归测试一票。尤其是一个项目做了半年以上功能不断叠加老的逻辑不能坏新的功能又要覆盖。每个版本都要全部手工点一遍不现实只测改动相关的功能又不放心。这时候用例库就是底气来源。有了结构化的用例库回归前你只需要做两件事第一根据本次改动的影响范围筛选出相关模块的用例第二把筛选出来的用例按优先级排列时间充足就全跑时间紧张就优先跑P0和P1级别的核心用例。没有用例库的时候回归全凭记忆力漏掉一个角落都可能造成线上事故。我经历过一次印象特别深的回归测试事故。当时项目要发一个大版本前后端都有改动测试排期只有三天。团队里资深的同事请了假剩下一个新人对着系统无从下手——因为她根本没有可参考的用例清单只能看哪点哪。结果上线后一个老订单导出功能挂了因为这个功能没有写进当次的需求文档里属于回归盲区。如果有一套完整的用例库这种问题完全可以避免。1.3 用例是沟通工具新人、产品和开发都能看懂用例的价值不止在测试团队内部。它是整个项目组对话的通用语言。对新人来说一套好的用例库是最快的学习材料。我见过不少刚入职的测试同学拿到一个不熟悉的模块不知道从哪下手翻用例库比翻什么文档都管用。用例里写清楚了前置条件、操作步骤、预期结果照着走一遍系统的主要行为路径就清楚了比看代码快得多。对产品和开发来说测试用例是需求理解是否一致的试金石。你以为需求里的登录成功是指跳转到首页并显示用户名开发实现的是只跳转首页产品想要的是还要弹一个欢迎弹窗——这种理解偏差在用例评审阶段就能暴露。我曾经在一次用例评审会上拿着一条登录成功后检查首页右上角用户昵称的用例问产品对方愣了一下说这个需求确实没写清楚但用户应该看到自己的昵称。于是当场补充了需求。没有用例评审这个问题会直接漏到测试执行阶段最后变成开发、产品、测试三方扯皮。2. 七种设计方法逐个拆规则、案例、还有常见误用接下来是重头戏测试用例设计的七种经典方法。这七种方法不是让你每次写用例全部用一遍而是像工具箱里的不同工具遇到不同的测试对象选最趁手的那个。2.1 等价类划分用最少的输入覆盖最多的可能性等价类划分的核心思想一句话就能说清把输入数据按是否会导致相同的处理逻辑分成若干类每个类里挑一个有代表性的值来测因为同一类里的其他值被测系统会用同样的方式处理测了也是白测。拿最常见的注册功能举例假设用户名字段的需求是必填6到20个字符只能包含字母和数字。那输入空间就无穷大了吗并不是。按需求可以划分成有效等价类6到20位的字母数字组合无效等价类长度小于6位、长度大于20位、包含特殊字符、为空每一类选一个代表值比如abc123代表有效类abc代表过短类aaaaaaaaaaaaaaaaaaaaa21位代表过长类abc123代表非法字符类 代表空值。五条用例就把这块逻辑覆盖了。这里有一个很多人会犯的错误只划分了有效和无效两大类忽略了一个输入可能有多个独立属性。还是用户名这个例子6到20位和字母数字其实是两个维度的约束组合起来应该是好几类而不是简单两类。正确做法是每个维度正交地进行划分。如果你用思维导图或者Excel列一个矩阵每个约束条件占一列每个取值方向占一行就不容易漏。等价类划分的适用场景是所有有明确输入规则的功能。它是所有设计方法里最基础、最常用的一种也是面试里考得最多的一个建议一定要吃透。2.2 边界值分析缺陷最偏爱的那条临界线边界值分析可以理解为等价类划分的孪生兄弟而且实战中比等价类划分更能抓到bug。原因很简单程序员写代码判断边界时最容易犯差一错误——本应是大于6写成大于等于6或者边界判断的顺序写反了。边界值分析的核心就是对每个输入条件的边界值本身以及刚过边界的值单独设计用例。继续用上面用户名6到20位的例子。单纯用等价类划分取一个7位和21位就够了。但用边界值分析要把这些边界点都覆盖上5位小于最小值的边界6位最小值本身7位刚过最小值19位刚接近最大值20位最大值本身21位超过最大值六条用例把边界区域彻底围住。实际项目里我见过一个金额输入框需求是1到9999元开发写的校验条件是金额大于1且小于9999结果等于1元和等于9999元都被拦截了。这种bug你拿等价类划分取一个500元是测不出来的只有边界值分析能抓出来。边界值分析不只用在上限和下限。如果需求里还有其他边界条件比如字符串以a开头列表为空数组下标为0都是边界点。另外要注意边界值不只是针对输入数据对于输出结果、操作顺序的边界同样适用。2.3 判定表与因果图条件组合太多时的解法等价类和边界值解决的是单个输入的问题但现实中的需求往往是多个条件共同决定一个结果。比如登录功能的规则可能是这样的账号存在A密码正确B账号未被锁定C三个条件都为真登录成功账号被锁定提示账号已锁定密码错误提示密码错误账号不存在提示账号不存在。这种场景每个条件有真、假两个状态三个条件就有2的三次方等于8种组合。如果四个条件就是16种。逐一枚举组合用例数量会爆炸而且没有章法。判定表的结构很清晰左边是条件桩和动作桩右边是条件组合和对应的动作。你把所有条件组合罗列出来再逐个分析每种组合下系统应该有什么行为。上面登录例子的简化判定表可以画成这样条件/动作12345678A 账号存在YYYYNNNNB 密码正确YYNNYYNNC 账号未锁定YNYNYNYN登录成功X提示密码错误XX提示账号锁定XX提示账号不存在XXXX这个表一出来你就知道哪些组合是合法的、哪些是互斥或不合理的用例覆盖情况一目了然评审时也方便和产品核对每一条业务规则的预期结果。因果图是判定表的图形化前置步骤画起来比较繁琐现在很多测试同学直接跳过因果图从需求里梳理条件和动作直接列判定表效率更高。我个人的建议是因果图可以了解但实际工作中判定表更实用能直接用。2.4 正交实验设计用组合数学省用例判定表能处理条件组合但条件一多全组合的用例数量还是太多。比如一个查询页面有四个筛选条件每个条件有四个选项全组合是4的4次方等于256条用例这谁跑得动正交实验设计法的思路是不测全部组合只测具有代表性的组合这些组合能保证任意两个条件之间的所有水平组合至少出现一次。换句话说它牺牲了一部分高阶组合的覆盖率换来了用例数量的大幅下降。最常见的应用是用正交表来排用例。四因素三水平的例子可以直接套用L9(3^4)正交表9条用例就能覆盖所有两两组合。很多测试工具里内置了正交表生成功能也可以在线查表不必自己计算。比如一个筛选页面条件有分类图书/数码/服饰、价格区间0到100/100到500/500以上、排序方式综合/销量/价格、是否只看有货是/否这一眼看过去全组合要3乘3乘3乘2等于54条用例。用正交法可以简化为L9(3^4)表9条用例搞定两两组合覆盖再手工补充一两条关键的三阶组合覆盖能力已经相当不错。实际使用正交法时有一个注意点正交表适合条件之间没有明显业务逻辑关联的输入组合比如筛选条件、表单字段如果条件之间有强制的业务依赖比如选了A就不能选B那部分组合是无效的要先用判定表把合理性过滤掉不能盲目套正交表。2.5 场景法从用户真实操作路径反推用例前面几种方法都是从输入角度出发场景法换了一个思路从用户的操作流程出发。它特别适合测试那些有明确业务流程的系统比如电商下单、审批流、订单处理。场景法以用例场景为单位通常先画出一条基本流然后不断迭加备选流和异常流。比如电商下单流程的基本流是用户登录→浏览商品→加入购物车→结算→填写地址→支付→下单成功。从这条主线上可以发散出无数备选流备选流一商品库存不足下单失败备选流二购物车为空时直接结算备选流三支付过程中取消支付备选流四优惠券已过期或不可用备选流五地址未填写完整每条备选流和基本流组合在一起就是一个完整的测试场景。场景法的好处是贴近真实用户行为能覆盖到端到端的集成问题而不仅仅是单个功能点的正确性。如果要把场景法用到极致建议从两个来源挖掘场景一是需求文档里明确写的业务流程二是真实用户的操作日志。很多系统上线后统计一下用户操作路径你会发现你设计的所谓基本流用户根本不走他们走着各种你没想到的路径。把这些真实路径补充成用例比闷头按需求文档设计更能发现问题。2.6 错误推测法没有公式但最考验经验错误推测法是一个很特殊的方法——它没有固定规则完全靠测试人员的经验、直觉和对系统的理解去猜测哪里容易出问题然后针对性地设计用例。典型的错误场景包括网络异常、并发操作、重复提交、资源耗尽、缓存过期、权限越界、异常断电等。比如一个保存按钮正常点击一次保存成功但如果用户手抖双击了会发生什么很多开发不会在按钮层面做防重复提交于是数据库里出现两条重复数据。这种bug你在需求文档里找不到任何线索纯靠经验推测出来。错误推测法和前几种方法不是一个维度的东西它更像一种补充策略。正确的用法是先用等价类、边界值、判定表这些方法把结构化用例铺满然后发挥经验和想象力在关键路径上补充一批错误推测用例。我常用的推测切入点包括所有输入框尤其是金额、日期、手机号、所有按钮双击、长按、快速切换、所有列表页空数据、超大数据量、翻页边界、所有涉及状态流转的地方订单取消后退货、支付超时后重新支付。这些地方每轮测试都要专门过一遍踩过的坑多了错误推测的命中率会很高。2.7 状态迁移法状态多的系统最好用它有些系统的核心逻辑是状态驱动比如订单状态、审批状态、设备工作状态。这类系统用状态迁移法最合适。订单的状态无非是待支付、已支付、待发货、已发货、已完成、已取消、已退款。但状态之间不是随便跳的待支付可以到已支付也可以到已取消已支付可以到待发货也可以发起退款已发货可以到已完成已取消不能直接到已完成状态迁移法就是把这些状态和触发条件画成一张状态图然后针对每个状态转移路径设计用例。重点是覆盖所有合法的状态转移同时验证非法的状态转移是否被正确拦截。举一个实际的坑某系统里已取消的订单在管理后台点发货按钮仍然能发货成功——因为后端没有校验状态只校验了订单号。这就是典型的缺失状态拦截校验。用状态迁移法画完状态图你马上就会发现这条非法路径没测但要靠功能点点点不知道要多久才能踩到这个角落。3. 粒度怎么定一句话用例和多步骤用例的取舍写用例时最容易纠结的一个问题是一条用例到底写多细写粗了执行时还得靠临时临场发挥写细了几百条用例光描述就写到吐维护成本也高得吓人。3.1 粒度粗有粗的好处细有细的成本用例粒度本质上是在覆盖度和维护成本之间做权衡。粗粒度的用例比如验证用户能正常登录优点是写得快、维护容易、需求变化时改起来不心疼缺点是执行时过度依赖执行者个人理解不同的人执行结果可能完全不同——A觉得验证了跳转就算通过B非要检查cookie和token标准不一致。细粒度的用例比如逐条写清楚1. 打开登录页2. 输入用户名admin3. 输入密码1234564. 点击登录按钮5. 验证页面跳转到首页并显示用户昵称优点是执行者不需要动脑子照着做就行新人也能直接上手缺点是写起来耗时巨大而且一旦前端交互方式调整比如按钮位置变了、登录页改成弹窗这类用例就要大面积返工。3.2 我常用的分级策略冒烟级、功能级、脚本级我的做法是按面向的使用场景对用例分级而不是所有用例一个粒度标准。第一级是冒烟级也可以叫主流程用例。整个系统或模块最核心的业务链路通常只需要几条到十几条。粒度可以稍微粗一些重点验证主干功能是否可用。这类用例是每次提测后第一轮快速验证用的目的是尽快发现能不能测下去的问题。第二级是功能级常规功能用例。对单个功能模块的完整测试粒度适中。每个步骤写清楚操作对象和关键数据但不需要每一步都精确到点击屏幕哪个位置。预期结果要明确最好能写清楚验证点。这类用例是日常功能测试的主力数量最多覆盖了等价类、边界值、判定表等各方法设计出的用例。第三级是脚本级自动化用例。这类用例面向自动化测试框架每次都按脚本逐字全量执行不需要人为判断。粒度必须细到每一步都无歧义定位符、输入数据、断言点全部写清楚。因为自动化脚本没有临场发挥的能力你写得含糊一点脚本就会跑挂或误判。对绝大多数团队来说把用例明确分成这三个粒度比统一用一种粒度合理得多。低级用例追求数量高级用例追求可靠性。3.3 用例模板里哪些字段可以按粒度裁剪标准的测试用例模板通常包含用例编号、所属模块、用例标题、优先级、前置条件、测试步骤、输入数据、预期结果、实际结果、执行状态、备注。字段看起来很全但不是每条用例都需要全部填满。粗粒度的冒烟用例前置条件和测试步骤都可以简化标题写清楚意图就行。细粒度的脚本级用例则必须完整填好所有字段尤其是前置条件和预期结果。实际项目里粒度细的用例更多用于核心模块和易错模块风险低的模块用功能级甚至冒烟级的粒度就足够了不必一刀切。4. 用例算不算好从覆盖率、有效性和可维护性三个维度看最后回答一个很多人不好意思问的问题写完了用例怎么评价它写得好不好这个功能我测了20条用例到底够不够评审的时候别人问起来怎么判断一套用例是不是合格的4.1 覆盖率先看需求有没有被全部翻译成用例评价用例的第一个维度是覆盖率。这里的覆盖率不是代码覆盖率而是需求覆盖率——每一条需求有没有对应的测试用例尤其是关键功能点有没有被覆盖到。实际操作中我会把需求文档里的功能点列成一张追踪矩阵每一行是一条需求每一列是与之相关的用例编号。评审的时候先把这张矩阵拉出来过一遍发现需求条目后面空着就是漏洞。但要注意覆盖率不是越高越好。覆盖率从90%提升到95%可能要多付出30%的用例编写和执行成本。合理的做法是为功能点分级关键路径和核心功能要求全覆盖边缘功能按风险决定覆盖到什么程度。一个简单的判断标准是这个功能出了问题用户能不能感知到感知到之后损失有多大据此分配覆盖密度。4.2 用例有效性能不能发现缺陷说了算覆盖率衡量的是该测的有没有测而有效性衡量的是测完有没有用。一套用例如果执行下来一个缺陷都发现不了不能说它好——最多说明被测系统质量好。我习惯用两个指标来度量决策缺陷发现率每个用例执行完统计当前用例库在历史上总共发现了多少个缺陷。缺陷发现率为0的用例要重点审视是冗余了还是设计方向错了。用例密度与缺陷密度比某个模块的用例数量占总用例的百分比和该模块的缺陷数占总缺陷的百分比对比一下。一个模块只占10%的用例却贡献了40%的缺陷说明这个模块的用例严重不足需要补充。有效性这个维度还要求用例的反向覆盖足够。我评审用例时看到全是正向用例会格外警惕。好的用例库一定是正向反向都齐全的甚至在一定程度上反向用例更能体现设计功力。一条验证错误提示文案正确的用例往往比十条正向用例更能发现问题。4.3 可维护性与评审用例不是写了就结束第三个维度是可维护性。用例是活的文档它要跟着需求变更、代码重构持续更新。如果一套用例写得像一潭死水需求改了一个月用例库还停留在旧版本那这套用例的价值就会快速衰减最终被团队放弃。用例的可维护性评估重点有四个是否独立一条用例是否只验证一件事。把多个独立验证点塞进一条用例执行时一个节点失败整条用例标红定位问题还要从头再测一遍非常低效。是否有明确的前置条件和预期结果缺了这两项用例就是半成品执行时全靠猜。是否避免重复和冗余我曾见过一个模块的用例库光正确登录就有六条变体区别只是执行顺序换了换。这种重复不提升覆盖率只增加维护负担。是否易于自动化改造如果团队后续要做自动化测试用例写得好不好直接决定了改造工作量。断言明确、步骤精简、数据独立的用例转成自动化脚本很顺畅。评审是保证用例质量的关键环节。评审时除了测试团队一定要拉上产品和开发。产品能确认预期结果是否符合业务预期开发能判断用例里写的前置条件和步骤是否和代码逻辑一致。很多需求理解偏差和接口设计问题都是在这种跨角色用例评审中被提前发现的。4.4 用数据复盘不断优化用例库用例库建设是一个持续迭代的过程不是一个版本的产物。我现在的做法是每个迭代版本测试结束后把线上问题和漏测缺陷拉出来开个复盘会逐个分析它们为什么没有被用例覆盖。漏测的缺陷一般只有三个原因需求里没有、用例里没有、执行时漏跑。需求里没有的补需求文档同时补用例用例里没有的设计时方法没用对复盘后补充进用例库执行时漏跑的检查是筛选逻辑不对还是执行遗漏。每次复盘都会让用例库变得更完善。这个反馈闭环坚持下去用例库会成为整个团队最有价值的质量资产。这套方法我用了很多年不敢说把每个项目的用例都设计得滴水不漏但至少能保证测试有章法、回归有底气、漏测有复盘、改进有方向。用例设计本质上是把一个模糊的测一测变成明确的测这些、这样测、测到这样算过这是一切测试工作的地基。地基打得深项目才能走得稳。