新闻详情

新闻详情

首页 / 资讯中心 / 详情

软件测试用例设计四方法:等价类、边界值、场景法、因果图实战解析

发布时间:2026/9/9 22:10:19来源:尧图网络
软件测试用例设计四方法:等价类、边界值、场景法、因果图实战解析
1. 先把话说清楚这四个方法不是“四选一”是同一场测试的四个切面经常有测试同学问我等价类、边界值、场景法、因果图面试题背得滚瓜烂熟一上手写用例就不知道用哪个。还有些人喜欢问“这四种方法哪个最好”我一般会反问一句你想用一把螺丝刀还是用一套工具箱这四个方法压根不是竞争关系它们是从不同角度看同一份需求——等价类负责把无穷输入切成有限几筐边界值负责在筐边上看有没有漏场景法负责把这些筐串成用户真实走的流程因果图负责处理条件之间那些“说不清道不明”的组合约束。这篇文章就用一个实际业务模块从头到尾走一遍我会拿一个在线商城“订单结算优惠”功能当贯穿案例。你跟着我把这份需求拆完会发现原来用例设计不是靠灵感而是靠方法组合。这个案例的需求规则如下后面所有方法都会围绕它展开商品总价满199元系统自动减30元满减活动优惠券分三种新人券5元无门槛、品类券满99减20、店铺券满299减50叠加规则新人券可以和满减叠加但不能和品类券同时使用品类券可以和店铺券叠加但优惠总额不超过订单金额的50%每笔订单最多使用2张优惠券优惠券必须在有效期内且用户等级达到领券等级才能使用。是不是看着还挺常见的但真让你把用例写全很多人会漏。下面逐个方法过。2. 等价类划分先解决“测哪些”别急着写具体数字2.1 从需求里提取输入条件和规则等价类划分的核心动作是“抽象”。你可以把需求里所有能被用户输入、被系统判断的东西都拎出来这些就是划分对象。在订单优惠模块里输入条件至少包括商品总价决定是否触发满减优惠券类型新人券、品类券、店铺券优惠券数量用户选了几张券优惠券有效期状态未开始、有效中、已过期用户等级是否达到领券等级优惠券叠加组合方式。等价类本质上是把“无限多的具体值”归成“有限几类特征”。比如商品总价这一个输入在系统看来不关心它是100块还是200块只关心它是否满足“大于等于199”这个判断。你测100和测200对满减逻辑来说走的是同一条代码路径——这就是为什么要归类。2.2 有效等价类和无效等价类的划分实例拿“商品总价”和“优惠券有效期”两个条件举例划分结果是这样的输入项有效等价类无效等价类商品总价满减门槛内金额≥199不满减金额199商品总价0元边界订单异常但可能存在负数、非数字优惠券有效期未开始理论上不可用已过期优惠券有效期有效期内日期格式非法用户等级达到券种等级要求未达到等级要求这里有个新手容易犯的毛病只画有效等价类把无效等价类当“反正都会报错”忽略掉。实际上大量线上故障都出在无效数据的处理上比如过期优惠券在后端被当成“有效券”参与优惠计算直接导致用户以错误价格下单。无效等价类不是凑数它测的是系统的“防守能力”。还需要注意一点一个等价类并不总对应一条用例。比如“商品总价 199”这是一个无效等价类但你可以在这个类里选99、198、0各测一遍因为它们在满减判断之外还可能触发其他逻辑比如0元订单是否允许提交。等价类先帮你锁定大类再谈细节覆盖。2.3 等价类设计最容易忽略的“伪等价类”我见过不少测试方案把“新人券”和“店铺券”划分成两个独立等价类然后各测一张就收工。这在单券场景下没问题但需求里写了“叠加使用”叠加后的行为已经不是“两张单券行为之和”而是一个新的等价类。所以等价类划分要特别小心判断依据不是“长得像”而是“系统处理路径是否相同”。新人券单独用是一条路径新人券满减叠加是一条路径新人券品类券被禁止又是一条路径。这三条路径对系统来说差异很大必须分成不同的等价类来覆盖。等价类的产出通常是一张表它不需要精确到具体数值但必须能回答“测试范围覆盖了哪些输入域”这个问题。范围没框好后面所有方法都白搭。3. 边界值分析别只知道0和最大值矩阵元素的边界也在这套逻辑里3.1 为什么Bug总爱躲在边界上做了这么多年测试我总结出一个规律程序里60%以上的逻辑错误都出在边界判断上。原因很简单开发写代码时最常见的判断就是if (amount 199)或者if (count 2)他们自己也容易搞混“大于”和“大于等于”更别提循环里的i length和i length差一个单位可能就直接数组越界。边界值分析的核心就是针对等价类的边界取恰好等于、刚好大于、刚好小于边界的值作为测试数据。它和等价类配合使用时能最大程度覆盖代码中的比较运算符和循环判断。3.2 优惠模块里的边界值该取哪些数满199减30边界值是198、199、200这个多数人会取。但我要提醒:三个值怎么落到用例上是有讲究的。“满199减30”这个规则里198和199之差不只是一个数字之差而是“触发满减”和“不触发满减”两条路径的分水岭。198测的是不触发路径的上限199测的是触发路径的下限——这两个值必须同时出现在用例集里缺一个就有盲区。再比如“每笔订单最多使用2张优惠券”边界值是1、2、3。选券数量1是“未达上限”2是“恰好达到上限”3是“超过上限”。注意超过上限的场景必须验证系统是阻止操作还是静默丢弃需求里如果没有明说这就是一个要和产品确认的需求缺陷不是单纯测试用例能兜住的事。优惠券有效期也是一个典型的边界场景。券的有效期如果是“2024-01-01 00:00:00 到 2024-12-31 23:59:59”那么需要考虑的边界包括下单时间恰好等于生效时间秒级精度下单时间等于过期前最后一秒下单时间等于过期时间之后一秒。有些系统在存储时间精度上不一致有的用秒有的用毫秒这会导致“恰好等于”的判断出现偏差。这种差一秒的问题最容易在生产环境被用户抓到因为用户不会精确到秒下单但定时任务会自动触发。3.3 顺着“矩阵元素的边界值”这个热词聊聊多维数据的边界最近“矩阵元素的边界值”这个词挺热很多人以为是数学题。但对测试来说这个词其实点出了一个很实在的场景被测对象是一张二维表、一个矩阵甚至一个多维数组时边界分析不能只盯着“值”的边界还要盯着“位置”的边界。我做过一个优惠规则配置平台后端把“用户等级 × 券类型 × 订单金额区间”存成了一张二维矩阵。这张矩阵本身不大但测试时发现一个诡异的问题在矩阵第0行第0列的元素上配置规则后前端死活不生效其他位置都正常。查了半天发现是前端遍历矩阵时用了i rows最后一轮循环越界访问到了下一个内存块把首地址的数据覆盖了。这就是典型的“矩阵位置边界”问题。所以当你处理矩阵、数组这类数据结构时边界值分析要分两层来做值边界矩阵元素本身的大小边界比如优惠金额是否为0、是否为负数、是否超过订单金额的50%下标边界遍历时的最小下标0、最大下标rows-1、cols-1以及越界后的访问行为。具体到用例层面至少要有这些场景测试数据矩阵最小值位置[0,0]位置配置规则矩阵最大值位置[rows-1, cols-1]位置配置规则单行矩阵1×N矩阵的遍历单列矩阵N×1矩阵的遍历空矩阵0行0列时页面是否报错临界值元素矩阵中某个元素恰好等于阈值这里有个反直觉的经验很多人觉得空矩阵肯定不会测但实际产品里“还没有配置任何规则”恰恰是上线第一天最常见的状态。一旦空矩阵没有兜底逻辑用户打开配置页直接白屏这就是一级故障。边界值分析的教训永远是同一个不要想当然。你以为边界是100实际代码里可能用的是99.99——因为浮点数在计算机里不能精确表示开发为了规避精度问题会偷偷做偏移。所以如果你在测试中发现边界值行为不符合预期不妨打开日志看看真实比较逻辑往往会有惊喜。4. 场景法把用例串成一条用户真会走的流程4.1 场景法从哪里来基本流和备选流等价类和边界值最大的问题在于它们都在“单点”上做文章而用户真正操作时是一连串动作。用户可能先选商品、再领券、结算、选择优惠、提交订单——任何一步出错整个流程的行为都可能改变。场景法就是解决“点”到“线”的问题。场景法来源于事件流分析它把业务流程抽象成一条基本流主成功路径和若干条备选流分支路径、异常恢复路径。用例设计的目标就是覆盖基本流、尽可能覆盖备选流。4.2 订单使用优惠券的完整场景拆解订单结算这个业务基本流很清晰用户选择商品进入结算页系统计算商品总价系统自动匹配满减活动用户勾选优惠券系统计算优惠总额并校验叠加规则用户提交订单系统生成订单记录。备选流就多了我列一部分商品总价未达到满减门槛用户没有可用的优惠券用户勾选新人券后又勾选品类券触发“不可叠加”规则用户同时勾选品类券和店铺券但优惠总额超过订单金额50%用户提交订单时优惠券已过期用户等级不满足优惠券使用条件用户点击提交后网络异常订单实际已创建。把基本流和备选流组合成场景就得到了场景列表场景编号场景描述包含事件流S01正常下单使用满减新人券基本流 满减触发 新人券勾选S02正常下单未达到满减门槛基本流 备选流1S03新人券与品类券冲突基本流 备选流3S04品类券店铺券叠加但优惠超过50%基本流 备选流4S05下单时券已过期基本流 备选流6S06用户等级不足基本流 备选流7你会发现场景法很自然地把之前等价类里“单点覆盖”的结果组合成了“整条路径覆盖”。这正是场景法的价值——它用来验证的不是“优惠券能不能用”而是“用户整个下单过程顺不顺、错时错得准不准”。4.3 场景粒度控制别把每个if都写成场景新手写场景法最容易把粒度切得太细。一个优惠券模块硬是写出30多个场景评审时大家越看越晕。我自己的经验是一条场景必须能对应一个“用户可感知的结果变化”。比如“用户点击满减标签时标签变灰”这种UI细节适合用等价类加界面用例去覆盖不太适合当成场景法的独立场景。但“满减标签变灰且满减金额不计入优惠总额”就是一个合格场景因为它的结果是用户可以感知到的金额变化。另一个经验场景法用例要标注“前置条件”。同一个备选流在不同前置条件下走出来的结果是完全不同的。拿“下单时券已过期”这个场景来说前置条件是用户已经勾选该券但一直没提交还是用户刚进入结算页还没勾选——这两种情况系统一个应该提示“券已过期请重新选择”另一个应该在下单时自动剔除该券并重算金额。不写清楚前置条件测试执行时很容易产生争议。5. 因果图处理“多个条件组合”的硬骨头5.1 因果图背后的直觉条件的组合与约束等价类、边界值、场景法都有一个共性它们默认条件之间是相互独立的。但现实项目里条件往往互相牵制。比如“新人券不能用但品类券能用”“不能同时用但可以叠加满减”——这种话就是因果逻辑直接用等价类去套很容易漏组合。因果图法是这么干的把需求中的“因”输入条件和“果”输出结果提取出来用逻辑关系连接起来再通过约束关系剔除不可能的组合最后转成判定表生成用例。它解决的是“条件组合爆炸”问题。5.2 从优惠规则到因果图的建模过程回到案例我们把优惠叠加规则中的关键条件和结果拎出来C1订单金额 ≥ 199C2用户选择了新人券C3用户选择了品类券C4用户选择了店铺券C5优惠总额 ≤ 订单金额的50%E1可以使用当前选择组合E2提示优惠券组合不可用。用因果图表示这组逻辑可以得到如下的规则关系C1 与 E1 是“与”关系满减触发与否不影响券组合是否能用注意满减单独判定C2 与 C3 是“排斥”关系两者不能同时选C2、C3、C4 与 E1/E2 之间是“或/与”组合C5 是 E1 的强制条件不满足则E2。这个建模过程本身就会逼着你把需求里模糊的措辞变成精确的逻辑。比如“新人券可以和满减叠加但不能和品类券同时用”这句话因果图建模时就必须明确如果你勾选了新人券又勾选了品类券系统是直接禁止提交还是只保留金额更高的那张需求没说清楚这就是一个需求缺陷。5.3 判定表转用例组合爆炸时怎么“有车可坐”因果图本身不是直接产出用例的它的价值是帮你推导出完整的判定表。判定表把条件和动作做成行列矩阵每一列就是一个规则组合。拿上面的C1~C5来说去掉约束条件全组合是2的5次方32种。加上约束条件后C2和C3不能同时为1有效组合一下降到20种不到。这个数量完全可以支撑用例设计不需要再盲目扩充。有人会问那我有pairwise成对组合工具是不是不需要因果图了我的看法是pairwise是算法层面的优化因果图是理解层面的建模。你连条件之间的约束关系都没理清楚pairwise生成的组合再均匀也是空中楼阁。实际项目中我是先手工用因果图把约束关系和强相关规则理清楚再用工具辅助补充低频组合。从判定表转用例时有一条很重要的经验每条规则都要明确预期结果不明确的规则本身就是测试发现的需求问题。比如“用户等级不足但优惠券仍在有效期内”这个组合对应的E结果应该是“不可用且提示等级不足”如果开发实现成“直接忽略券”那就是一个提示信息缺陷。6. 四种方法合体从一份需求到完整用例清单6.1 方法选型不是看“哪个高级”而是看“被测对象长什么样”我见过一些测试方案不管什么需求都套场景法用例十几个然后就说覆盖完成了。这就是没有理解方法的适用边界。做一个方法选型我一般看四个维度被测对象特征推荐方法原因输入域大、数据类型多等价类压缩测试规模先框范围有数值范围、边界条件边界值聚焦最容易出错的临界点业务流程明显、步骤多场景法覆盖端到端路径条件之间存在多种组合和约束因果图理清逻辑关系避免遗漏组合这四个维度并不互斥。实际需求往往同时具备几种特征所以最终方案是“以某一种方法为主线其他方法做补充”。比如我们这个订单优惠模块我会以场景法为主线组织用例因为它的业务流程最核心在场景内部再用等价类和边界值完善每个步骤的取值条件组合部分用因果图推导出的判定表补充覆盖。6.2 完整落地一个“新人券品类券不可叠加”需求的用例清单基于订单优惠模块我整理一份精简但可直接落地的用例清单展示四种方法如何汇入一份方案用例编号设计的出发点前置条件操作步骤预期结果TC01等价类有效有满减活动用户有新人券选商品总价220元勾选新人券提交优惠总额满减30新人券535元订单实付185元TC02等价类无效有满减活动用户有品类券选商品总价150元勾选品类券提交满减不触发品类券因不满99不可用提示“未达到使用门槛”TC03边界值有满减活动商品总价199元不用券提交满减30元触发实付169元TC04边界值有满减活动商品总价198.9元不用券提交满减30元不触发实付198.9元TC05边界值商品总价120元品类券满99减20勾选品类券和店铺券提交店铺券因满299不满足不可用提示TC06场景法无结算页同时勾选新人券和品类券系统提示“新人券与品类券不可叠加使用”且不允许提交TC07场景法用户已领但券快过期勾选品类券停留到过期后提交系统自动移除该券并重新计算金额TC08因果图商品总价400元品类券店铺券同时勾选两种券提交优惠总额150元≥50%上限200提示组合不可用TC09因果图商品总价500元品类券店铺券同时勾选两种券提交优惠总额70元≤250元可用实付430元这份清单只有9条但四个方法的核心场景都被覆盖了。实际项目里每条用例还会补充优先级、测试数据、执行环境等信息这里不展开。6.3 用例评审时怎么自检一张查漏清单用例写完以后我习惯拿一张自查清单过一遍比对着覆盖率报告好用得多每个等价类至少被一条用例覆盖了吗无效等价类是否真的测了每个关键边界是否同时取了“边界值-1、边界值、边界值1”三个点每一条备选流是否至少出现在一个场景里异常恢复路径有没有因果图中的每组约束关系是否都有“满足约束”和“违反约束”两条用例用例的预期结果是否足够具体有没有出现“验证正确”这种说了等于没说的描述这个自查流程通常能帮我在评审前拦下一半的漏测。另一半往往要靠测试环境里的实际执行才能暴露。7. 实战中踩过的坑三个“反直觉”教训7.1 边界值不是比等价类“地位更高”顺序别搞反我见过不少测试新手接到需求上来就找边界100块、199块、299块的边界测了一堆结果最基本的功能路径没走通。这不是边界值的问题是使用顺序出了问题。等价类负责“测全”边界值负责“测准”边界值必须建立在等价类划分完整的前提下。先把输入域归类清楚再用边界值在每个类的边界上补刀顺序反了覆盖就是漏的。7.2 因果图最容易被误解的是“约束”不是“逻辑”很多人学因果图时盯着“与、或、非”看觉得自己懂了。到了实际项目里一用发现条件之间除了逻辑关系还有大量约束关系——两个条件不可能同时成立、一个条件成立另一个必须成立、一个条件最多有一个成立。这些约束才是因果图建模时最花时间的地方。我有个印象很深的经历某次需求写“每笔订单最多使用2张优惠券且同一品类券不能重复使用”测试时我盯着“最多2张”组合把“同一品类券不能重复”漏了。后来线上出现一个用户用两张同类品类券薅了一笔才发现开发实现时根本没做“同类不可重复”的判断。原因就是需求里的约束散落在不同段落没人把它收敛到因果图里。约束关系必须逐条从需求原文中摘出来不能靠“感觉差不多”。7.3 覆盖率100%不等于零漏测度量指标只是参考不是保险。我见过有些团队把用例覆盖率当作KPI用例全部执行通过就认为质量达标了。但实际上覆盖率只能证明“你设计的用例都测了”不能证明“你没漏设计什么”。最典型的例子是优惠计算中的精度问题9.9919.99这类浮点数相加在计算机里可能得到29.979999999999998显示时如果没做精度处理用户看到的价格就会错一分钱。这种问题等价类、边界值、场景法可能全都覆盖不到只有通过“代入真实业务数据”和“对金额计算做专项精度测试”才能发现。所以我一直强调方法解决的是“设计效率”问题真正决定质量的是“测试思维”——永远保持怀疑永远追问“还有什么情况我没考虑到”。这份怀疑精神才是等价类、边界值、场景法、因果图背后共通的底层能力。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

系统日志排障入门:不重装系统,从日志定位电脑故障 2026/9/9 22:46:28

系统日志排障入门:不重装系统,从日志定位电脑故障

做运维和电脑维修这些年,有一个原则我一直在坚持:电脑出问题时,绝不第一时间重装系统。碰到蓝屏、死机、开机变慢、软件闪退,我通常做的第一件事,就是打开系统日志,把故障现场还原一遍。系统日志不是那种只…

阅读更多 →
Puter SpaceInfo 存储空间对象指南:解读 `capacity` 与 `used` 字段及完整数据链路 2026/9/9 22:46:28

Puter SpaceInfo 存储空间对象指南:解读 `capacity` 与 `used` 字段及完整数据链路

Puter SpaceInfo 存储空间对象指南:解读 capacity 与 used 字段及完整数据链路 【免费下载链接】puter 🌐 The Internet Computer! Free, Open-Source, and Self-Hostable. 项目地址: https://gitcode.com/GitHub_Trending/pu/puter SpaceInfo 是…

阅读更多 →
screenshot-to-code 如何为 screenshot_preview 工具接入自定义渲染后端? 2026/9/9 22:46:28

screenshot-to-code 如何为 screenshot_preview 工具接入自定义渲染后端?

screenshot-to-code 如何为 screenshot_preview 工具接入自定义渲染后端? 【免费下载链接】screenshot-to-code Drop in a screenshot and convert it to clean code (HTML/Tailwind/React/Vue) 项目地址: https://gitcode.com/GitHub_Trending/sc/screenshot-to-…

阅读更多 →
Marlin固件稳定性测试怎么做,才能把3D打印翻车扼杀在开机前 2026/9/9 22:46:28

Marlin固件稳定性测试怎么做,才能把3D打印翻车扼杀在开机前

Marlin固件稳定性测试怎么做,才能把3D打印翻车扼杀在开机前 【免费下载链接】Marlin Marlin is a firmware for RepRap 3D printers optimized for both 8 and 32 bit microcontrollers. Marlin supports all common platforms. Many commercial 3D printers come w…

阅读更多 →
最小覆盖子串:滑动窗口+哈希表套路详解与Java实现 2026/9/9 22:46:28

最小覆盖子串:滑动窗口+哈希表套路详解与Java实现

做力扣 Hot 100 的题,很多人一上来就刷,刷完就忘,说到底还是没把一类题的“套路”吃透。今天拿一道很有代表性的题来说事——最小覆盖子串。这道题在 Hot 100 里排得上号,也是各大厂面试的高频题,更重要的是&#xff0…

阅读更多 →
Java对接微信商家转账到零钱:接口选型、签名与回调避坑指南 2026/9/9 22:43:27

Java对接微信商家转账到零钱:接口选型、签名与回调避坑指南

简介:面向Java开发者的微信企业转账到零钱功能实现资料,聚焦企业付款、工资奖金发放、退款等典型业务场景。资源包内含两个核心Java文件,一个用于生成请求签名,另一个封装转账接口调用与参数组装,可直接借鉴到Spring等…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞