
周一早会带的新同事小杨拿着一份用例评审材料来找我。材料倒是做得密密麻麻五十多条用例可我扫了两分钟就看出了问题一个手机号输入框他光测了各种合法号码和几个常见错误格式边界上的11位限制、首位为0的情况、旧号段与新号段的临界判断这些最容易出事的点一条都没有。评审会开了不到十五分钟就被开发指着两处用例反问这个场景代码里根本不存在。他有点委屈需求文档就那么几行能写出这么多条已经绞尽脑汁了。这其实是每个测试新人都要撞上的那堵墙不是想不出用例而是想出来的用例要么重复、要么漏测、要么根本测不到点子上。软件测试入门阶段的必修课之一就是测试用例设计方法——用最小的用例数量覆盖最多的有效场景。这篇是软件测试入门实战营Day2的内容我会把等价类、边界值、判定表、场景法这4种最常用的测试用例设计方法拆开讲透每一步都配上可以直接照着做的实操例子顺便把我这些年带新人时见过的高频翻车现场一并交代清楚。1. 一上来就写用例先想清楚测试设计的核心矛盾很多新人拿到需求文档后的第一反应是打开Excel把能想到的场景拼命往里堆。这个动作本身没有错但如果你没有先想清楚为什么要设计测试用例堆出来的东西大概率就是小杨那五十多条——看起来工作量很大实际覆盖质量很差。1.1 为什么看起来简单的功能最容易测漏软件测试有一个最基本的现实穷尽测试是不可能的。拿一个最简单的注册页面举例光手机号输入框这一个字段合法的号码、非法的号码、空值、超长、含字母、含特殊字符、前后带空格……每一种情况往下细分数量是无限的。再加上多个输入框之间的组合、网络异常、服务器返回超时你要把所有可能性都测一遍测到项目上线都测不完。这就是测试设计的核心矛盾有限的测试资源和无限的可能输入之间的矛盾。测试用例设计方法解决的不是怎么多写用例而是怎么在资源有限的前提下用最少的用例找到最多的缺陷。理解这一点你才不会陷入用例数量KPI的误区。1.2 测试用例设计方法解决的是同一个问题用最少用例覆盖最有效场景测试用例设计方法说白了就是一套怎么从无限可能性里抽样的思路。每一种方法都从不同角度切进这个问题等价类划分法把无限的输入数据按测了等于没测的原则分组每组取一个代表就够。边界值分析法等价类分组的补充专门盯着每组数据最容易出错的临界位置。判定表法处理多条件组合的逻辑关系把如果A且B则C这类规则一网打尽。场景法跳出单点输入从用户完整操作流程出发设计用例覆盖基本流和备选流。这4种方法不冲突实际工作中经常混合使用。我的习惯是拿到一个功能先画业务流程场景法再对每个输入框做等价类和边界值分析等价类边界值遇到条件组合复杂的规则就用判定表整理。这套组合拳打下来用例质量通常不会差。提示不要指望某一种方法包打天下也不要为了用方法而用方法。测试用例设计方法的本质是思维工具帮你把需求里隐含的规则、边界、异常情况挖出来而不是给你一个填完就完事的模板。2. 等价类划分先把无限输入砍成有限几类等价类划分是测试用例设计方法里最基础、最容易上手的一个也是后面所有方法的地基。它解决的是输入数据无穷多不可能全测这个问题。2.1 等价类的核心逻辑一组数据里测一个代表就等于测了全部等价类的思想来自一个假设对于同一类输入数据程序的处理逻辑是一样的你对其中一个数据的测试结果可以代表这一类数据的测试结果。举个生活化的例子。一个收银系统要求输入的金额必须是正整数范围1到9999。这时候3元57元888元这三个输入在程序眼里本质是一样的——都是合法的正整数走的都是同一条处理分支。你测了57元这个代表基本可以推断3元888元也没问题没必要把每一个正整数都测一遍。这就是等价类的核心把输入域划分成若干个互不相交的子集每个子集取一个代表值测试效果等价。子集划分得越合理用例设计效率越高。2.2 有效等价类和无效等价类必须分开测等价类划分要特别注意一个原则有效等价类和无效等价类要分开设计用例。有效等价类满足需求规格说明的输入数据预期结果是程序正常接受并处理。无效等价类不满足需求规格说明的输入数据预期结果是程序给出正确的错误提示或异常处理。很多新人犯的第一个错误是把多个无效等价类塞进同一条用例里。比如测手机号输入框输入12ab既长度不足又含有字母程序弹出了手机号格式错误你能判断是哪个条件触发的校验吗判断不了。所以一条无效等价类的用例最好只包含一个无效条件这样一旦测试失败你能立刻定位是哪个校验逻辑出了问题。2.3 一个手机号输入框的完整划分实操用一个最典型的例子走一遍完整流程。假设需求文档里写了这样一句话手机号输入框用户需输入11位有效手机号以1开头第二位为3、4、5、6、7、8、9中的任意一个限输入数字。根据这段需求我们可以先画一张等价类划分表用例类型等价类描述代表数据预期结果有效等价类满足所有规则的11位手机号13812345678校验通过无效等价类位数不足11位1381234567提示手机号格式错误无效等价类位数超过11位138123456789提示手机号格式错误无效等价类第二位不是3-912812345678提示手机号格式错误无效等价类以0开头03812345678提示手机号格式错误无效等价类包含英文字母1381234567a提示手机号格式错误无效等价类包含特殊字符138-1234567提示手机号格式错误无效等价类全部为空格11个空格提示手机号不能为空无效等价类为空不输入提示手机号不能为空注意观察这张表有效等价类只有1条用例无效等价类有8条。这就是等价类划分法的实操要点一个有效等价类可以只测一次但每个无效等价类最好单独测一次。因为程序对无效输入的处理逻辑往往是分开写的任何一个分支漏了都可能出bug。实操心得我带新人练习时要求他们先划等价类、编号再写用例。用例编号可以直接用TC-EC-01、TC-EC-02这种格式方便评审时按编号追溯需求。等价类的划分一定要从需求文档出发不要在脑子里凭空想需求里没有明确说明的规则先找产品确认边界别自己拍脑袋。3. 边界值分析最容易上手也最容易翻车边界值分析是等价类划分法的黄金搭档也是软件测试面试里出现频率最高的测试用例设计方法之一。它的基本思想是程序在边界位置出错的概率远大于中间值所以测试要重点覆盖边界。3.1 为什么缺陷总是藏在边界上开发写代码的时候判断条件经常写成if (x 0 x 100)这里的0和100就是边界。人写代码容易在边界上犯错用的是还是还是数组下标是从0开始还是从1开始这些错误在中间值上根本测不出来因为中间的输入无论判断条件是大于还是大于等于结果都一样只有踩到边界时和的区别才会暴露。边界值分析就是在等价类划分的基础上把每个等价类边界内外的值单独提取出来测试专门验证程序在临界状态下的行为。3.2 上点、离点和内点边界值背后的三个关键位置做边界值分析前先记住三个概念上点边界上的点正好等于边界值。比如范围是1-100上点就是1和100。离点离上点最近的那个点。这个要分区间类型闭区间[1,100]的离点是0和101边界外面最近的点开区间(1,100)的离点是2和99边界内侧最近的点。内点边界范围内的任意一点通常取中间值比如50。这个区分很关键我说个实际例子你就明白了。一个输入框要求输入1-100的整数闭区间上点是1和100离点是0和101内点选50。测试数据就是1、100、0、101、50这五个值。但如果需求写的是输入大于1且小于100的整数开区间离点就是2和99你再拿0和101去测反而测不到真正的边界逻辑。3.3 成绩0-100和年龄18-60两个例子把7点法彻底跑通实际工作中用得最多的是7点法最小值、次小值、正常值、次大值、最大值、略小于最小值、略大于最大值。为什么是7个点因为边界值分析要在等价类划分之后用通常一个有效等价类加上它旁边的两个无效等价类边界上关键位置就是这7个。拿学生成绩输入框要求0-100的整数举例测试点输入数据预期结果略小于最小值-1提示成绩必须在0-100之间最小值0校验通过次小值1校验通过正常值50校验通过次大值99校验通过最大值100校验通过略大于最大值101提示成绩必须在0-100之间再举一个注册年龄要求18-60岁的例子。边界值数据就是17、18、19、60、61再加一个正常值30。这里特别要注意17和61这两个离点很多新人只测18和60忘了测17和61结果开发把判断条件写成age 18 age 60时18和60都通过了17反而也通过了这个漏测就是典型的边界覆盖不完整。3.4 边界值最容易忽略的几个场景输入框有最大长度限制除了数字范围的边界还要测字符串长度的边界。比如用户名限20个字符要测19、20、21这三个长度。浮点数的边界如果输入允许小数要额外考虑精度问题。比如金额0.01-1000.00除了数值边界还要测0.009、1000.001这种超出精度的数据。数据表的边界列表页每页显示10条要测9条、10条、11条数据的分页表现。数组下标的边界如果被测对象是一个数组处理逻辑要关注第0个元素、最后一个元素、越界的下标访问。提示边界值分析建立在等价类划分的基础之上不要单独使用。先划等价类再在每个等价类的边界上补测试点这样才不会漏掉某些隐性边界比如字符串长度限制、数值精度限制等。4. 判定表条件一多、逻辑一绕用它最稳边界值适合解决单个输入域的问题但实际业务里经常出现多个条件组合后决定一个动作的情况。比如登录功能用户名是否正确、密码是否正确、验证码是否正确、账号是否被锁定这些条件组合起来可能产生十几种不同的处理结果。碰到这种场景等价类和边界值都不太够用就要请出判定表法。4.1 什么时候该用判定表判定表适合满足这几个条件的场景有多个输入条件每个条件有两个或多个取值不同条件组合会触发不同的动作或结果条件之间有明确的逻辑规则与、或、非。典型的例子包括登录验证、优惠券计算、审批流程、价格计算、权限控制。这些功能如果用想到一个场景写一条用例的方式去测很容易漏掉某些条件组合尤其是那些看起来不太可能发生但实际上会发生的组合。4.2 判定表的四要素条件桩、动作桩、条件项、动作项一张完整的判定表由四个部分组成条件桩列出所有可能的输入条件比如用户名是否有效。动作桩列出所有可能的处理结果比如允许登录提示用户名或密码错误。条件项每个条件在不同情况下的取值组合通常用Y/N或1/0表示。动作项在特定条件组合下系统执行的动作。构造判定表的步骤是先列出条件桩和动作桩然后列出所有条件组合2的条件个数次方再逐条判断每个组合对应的动作。4.3 登录功能判定表完整构造过程用一个简化版的登录功能当例子。假设需求规则如下用户名有效且密码有效且验证码正确才能登录成功用户名或密码错误提示用户名或密码错误验证码错误提示验证码错误账号被锁定提示账号已被锁定请联系管理员账号被锁定时不校验密码和验证码。这里条件桩有4个用户名有效A、密码有效B、验证码正确C、账号未锁定D。动作有4个登录成功、提示用户名或密码错误、提示验证码错误、提示账号锁定。完整条件组合是2的4次方16种实际构造时可以用一张表格列出来。我把简化后的几条关键规则写出来规则编号用户名有效(A)密码有效(B)验证码正确(C)账号未锁定(D)动作1YYYY登录成功2NYYY提示用户名或密码错误3YNYY提示用户名或密码错误4YYNY提示验证码错误5YYYN提示账号锁定6NNYY提示用户名或密码错误7NYNY提示用户名或密码错误或验证码错误按实际需求定构造判定表的过程实际上就是在逼你把每一条业务规则都显式列出来。很多时候需求文档里并没有把这些规则写全你在画判定表的过程中就会发现这个组合到底该怎么处理——这就是测试人员反推需求、暴露需求缺陷的价值所在。4.4 化简不是偷懒规则合并有讲究条件桩一多判定表的组合数量会指数级增长。4个条件16种组合还好6个条件就是64种全列出来不现实。这时候就要做规则化简把动作相同的多条规则合并成一条。比如上面规则2A为N、B为Y、C为Y、D为Y和规则6A为N、B为N、C为Y、D为Y动作都是提示用户名或密码错误。区别只在B的取值而B的取值不影响结果说明这里B是一个不关心项可以用-表示只要A为N且C为Y且D为Y无论B是什么都是提示用户名或密码错误。化简后的判定表更简洁可读性也更好。但要注意一个原则化简只能合并动作完全相同的规则动作不同不能强行合并。而且合并之前要想清楚这个不关心项在真实业务逻辑里是否真的不关心有时候只是你以为不关心实际程序里是分了不同分支处理的。实操心得判定表不是画完就完画完之后要把每条规则转化成测试用例。转化的时候每条规则至少对应一条用例覆盖条件项的组合和预期动作。判定表最大的价值不是那张表本身而是它逼你把所有条件组合都过了一遍——这个过程里你会发现很多需求文档里没写清楚、开发自己也说不准的场景这些就是Bug的高发区。5. 场景法从用户操作流程反推用例等价类、边界值、判定表都是在单点输入层面做文章但实际用户用软件的时候是从一个操作流到另一个操作流的。很多缺陷只有在完整流程中才会暴露比如某个页面在特定条件下跳转错误、某个中间状态没有做异常处理。场景法也叫业务流程分析法就是解决这个问题的测试用例设计方法。5.1 单个输入框没问题不代表整个功能没问题我见过不少新人按等价类和边界值把每个字段都测得很仔细但测完之后用户一操作就出问题。原因在于他们把功能拆成了一个个孤立的点忽略了点与点之间的连接路径。举个例子。一个电商下单功能你单独测购物车、结算页、支付页都通过了但用户从购物车→结算页→支付成功→订单列表这个完整流程走下来发现支付成功后订单列表里没有这条订单。这种问题靠单点测试是发现不了的必须用场景法从用户视角走完整流程。5.2 基本流与备选流ATM取款场景拆解场景法有两个核心概念基本流用户完成业务功能的最顺利路径没有任何异常和分支。备选流在基本流的基础上因各种原因出现的分支路径包括异常情况、取消操作、返回上一步等。拿最经典的ATM取款场景举例。基本流插卡 → 输入正确密码 → 选择取款 → 输入取款金额 → 出钞 → 取钞 → 退卡。备选流备选流1密码输入错误 → 提示重新输入 → 连续3次错误 → 吞卡。备选流2取款金额大于账户余额 → 提示余额不足 → 返回选择取款金额页面。备选流3取款金额大于单笔取款限额 → 提示超限 → 返回输入金额页面。备选流4点击取消 → 直接退卡 → 交易终止。备选流5ATM机内现金不足 → 提示本机现金不足 → 返回选择金额页面。备选流6操作超时无响应 → 吞卡并结束交易。场景法的用例设计就是把基本流和备选流组合成不同的场景每个场景对应一条或多条测试用例场景编号场景描述涉及流场景1正常取款成功基本流场景2密码错误但未超过3次重新输入后取款成功基本流 备选流1场景3密码连续错误3次吞卡基本流 备选流1重复3次场景4取款金额超过余额基本流 备选流2场景5取款金额超过单笔限额基本流 备选流3场景6用户在输入金额时取消交易基本流 备选流4场景7现金不足导致取款失败基本流 备选流5场景8用户长时间不操作超时吞卡基本流 备选流65.3 场景法用例怎么落地成可执行的测试用例场景画完之后不要停留在流程图层面要落成一条条可执行的测试用例。每条用例至少包含用例编号、前置条件、操作步骤、测试数据、预期结果。拿上面的场景4展开用例编号TC-ST-04前置条件账户余额为500元ATM机内有足够现金操作步骤插入有效银行卡输入正确密码选择取款输入取款金额800元点击确认。测试数据取款金额800账户余额500预期结果提示余额不足交易终止返回金额输入页面银行卡正常退出。实操心得场景法做出来的用例特别适合做冒烟测试和上线前的UAT用户验收测试。因为场景本身就是从用户操作路径来的覆盖了用户最真实的使用方式。设计场景时不要只看正常业务怎么走一定要问开发或产品用户最容易在哪里操作错、哪里会放弃操作这些地方就是备选流最丰富的区域也是缺陷密度最高的区域。6. 四种方法怎么搭着用选型思路与实战避坑把4种方法都过了一遍之后接下来是你真正每天工作中会遇到的问题拿到一个需求到底先用什么方法、怎么搭配、用例写到什么程度算完事。这一章我把自己的实战经验和踩坑经历都交代清楚。6.1 方法选型对照什么场景优先用什么不同测试用例设计方法有不同的适用场景我整理了一张选型对照表新人可以直接照着用场景类型推荐方法原因单个输入框的格式、范围校验等价类 边界值输入域是连续的最适合划分类别和测边界多个条件组合决定业务动作判定表条件组合多容易漏场景判定表可以系统覆盖完整业务流程、端到端测试场景法关注用户操作路径和状态流转条件特别多6个以上且组合爆炸判定表 正交试验法全组合不现实用正交表选取代表性组合基于历史缺陷和新人身经验的补充错误推测法不独立使用作为上述方法的补充手段这里多提一句错误推测法它不算是有明确步骤的方法更多靠测试人员的经验和对业务的理解猜测哪些地方容易出错然后针对性设计用例。新人可以多翻历史Bug记录那是错误推测法最好的素材库。6.2 用例设计不等于堆用例评审和可执行性同样重要回到开头小杨的例子。他的五十多条用例为什么被开发反问这个场景代码里根本不存在因为很多用例是为了写而写没有考虑可执行性。一条好的测试用例应该满足三个标准可追溯每条用例都能追溯到需求文档的某一条规则。追踪不到的需求要么是无效用例要么是需求文档本身有缺口。可执行测试步骤清晰任何人拿着这条用例都能照着操作不需要猜这里到底点哪里。结果可判定预期结果写得具体、明确而不是页面正常显示这种含糊表述。要说清楚显示什么内容跳转到哪个页面弹什么提示文案。用例评审不是走形式。每次评审前把用例和需求文档一一对照问自己三个问题需求里的每条规则我是不是都有用例覆盖漏掉的条件组合我是不是补上了每条用例的预期结果是不是经得起推敲这三个问题答不上来用例就不能算写完。6.3 踩坑记录我见过的新人典型错误这些年带新人有两个错误反复出现值得单独拎出来说。第一个错误一个无效等价类没有单独测导致Bug归属不明。有个新人测一个金额输入框一次性输入了-abc这个数据程序提示金额格式错误。他以为这个场景测完了实际上到底是因为负号被拦截还是因为字母被拦截完全分不清。后来开发改了代码把字母校验误改了这条用例依然通过因为负号还在问题被掩盖了。正确的做法是-1单独测一次abc单独测一次每次只动一个变量。第二个错误判定表只列正常规则的组合漏掉不可能发生的组合。比如优惠券计算新人认为用户未登录和优惠券已过期不可能同时出现就不列。但测试恰恰要验证这个不可能是否真的被程序正确拦截。如果开发也认为不可能没写校验用户真碰上这个组合时就可能出现优惠券被错误使用的结果。判定表里不要轻易删除任何条件组合除非你能在需求文档里找到明确依据。提示测试用例设计方法学到后面你会发现方法本身不难难的是对业务的理解和对哪里容易出错的敏感度。我的建议是每次设计用例时先用场景法走一遍主流程再用等价类和边界值抠细节遇到条件组合用判定表兜底最后花十分钟翻一翻历史Bug看看有没有遗漏的老坑。这套流程跑顺了你的用例质量会比只会堆数量的同事高出一大截。最后再分享一个实际工作中的小习惯。小杨后来把手机号输入框重新按等价类和边界值设计了一版用例从五十多条精简到十九条评审一次通过。他问我诀窍我说没什么诀窍就是每写一条用例先问自己一句这条用例对应需求里的哪条规则它能发现什么缺陷回答不上来的用例删掉也不可惜。这个习惯比任何方法都管用。