ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

因果图分析法:从逻辑建模到判定表的测试用例设计实战

因果图分析法:从逻辑建模到判定表的测试用例设计实战 做了多年的软件测试和需求分析我越来越觉得测试用例设计这门手艺真正拉开差距的往往不是等价类、边界值这些基本功而是面对一堆纠缠不清的输入条件时你能不能把逻辑理顺、把组合覆盖到位。因果图分析法就是我在这种情况下最常用、也最顺手的一件武器。它不玄乎本质上是把需求里“什么条件组合导致什么结果”的逻辑先画成一张图再转成一张表最后变成可执行的测试用例。这篇东西我把从画图到转判定表、再到生成用例的完整思路和踩坑经验都整理出来希望能给正在为复杂条件组合头疼的同行一些参考。1. 因果图分析法的核心逻辑与适用场景1.1 为什么等价类和边界值搞不定时就该轮到因果图先说说这个方法的定位。等价类划分和边界值分析擅长处理的是单个输入条件、或者彼此独立的多个输入条件。比如一个手机号输入框有效是11位数字无效是小于11位、大于11位、含非数字这些情况每个条件都能独立设计用例互不干扰。可一旦遇到这样的需求用户输入用户名和密码只有当两者都正确、且验证码也正确时系统才允许登录任意一项错误都给出对应提示此时条件之间就开始有“逻辑纠缠”了。这类需求的麻烦在于测试人员面对的不是“每个输入是否有效”而是“多个输入条件的组合如何决定最终输出”。更复杂的场景里还夹杂着优先级比如用户名错误和密码错误同时发生时系统只提示“用户名不存在”再比如某些条件下某些字段不可用、某些策略不生效。这些逻辑如果靠拍脑袋点几个组合去测很容易漏掉某个组合分支尤其当条件达到四五个以上时凭直觉枚举组合基本不可能完整。因果图分析法解决的就是这个问题。它把需求描述的因果关系当作一张逻辑网络来处理人为确定的“原因”是输入条件“结果”是系统响应用标准化的图形符号把两者之间的与、或、非以及各种约束关系画出来再把这张图转化为判定表最终设计出覆盖所有有效逻辑组合的测试用例。它不是替代等价类和边界值而是接手它们处理不了的那部分——多条件组合逻辑。1.2 什么样的需求最适合用因果图什么样的不适合从实际项目里摸出来的经验因果图分析法在下面这几类场景效果特别好条件之间存在明显的与、或、非关系组合结果多样。多个输入条件之间存在约束比如互斥选A不能再选B、要求选了C必须先选D、屏蔽出现E则F不生效。错误提示的优先级依赖条件组合同一类异常在不同组合下响应不一样。业务规则多比如优惠券能否叠加、订单状态能否流转、审批节点通过或驳回的分支条件、支付渠道的可用性判断。反过来如果需求本身没有逻辑组合只是一堆数值计算或者简单线性流程因果图就属于杀鸡用牛刀。举个典型的例子计算订单总价的规则是“商品单价乘以数量加上运费减去折扣”这个用等价类和边界值就能搞得明明白白强行画因果图反而浪费时间。因果图的成本在于建模和转表本身有一定工作量条件少于三个、结果单一的场景收益不大。1.3 因果图和判定表是前后脚的关系不是二选一不少文章把因果图和判定表分开讲好像它们是两种并列的方法。我实际用下来它们更像一套流水线的两个工序。因果图的价值在“梳理”——把让人头晕的文字需求变成一张一目了然的逻辑图判定表的价值在“落地”——把图里的逻辑关系展开成所有可能组合的二维表每一列就是一条规则可以直接对应成测试用例。画因果图的过程本身就是在帮测试人员强制建立全局逻辑观。很多时候我画着画着就会发现需求里的矛盾点比如某个结果在约束条件下根本不可能达成或者某个因被遗忘了再或者某两个条件放在一起永远为假根本测不了。这些用文字通读需求时很难一眼看穿一旦落到图形化、结构化的表达上逻辑漏洞自己就会冒出来。这也是为什么我一直建议团队做复杂需求时先画因果图再转判定表这个顺序不要反过来。2. 因果图设计的完整流程与实操步骤2.1 从需求文本中提取原因与结果这一步决定了成败画因果图的第一步不是急着连线而是先把需求里的“原因”和“结果”都摘出来。我的习惯是把需求文档打开从头到尾逐句读凡是看到“如果……那么……”“当……时……”“……才……”这类描述都高亮出来。原因通常是输入条件、中间状态、触发动作结果则是系统产生的响应、输出、提示或状态变更。打个比方把需求想象成一个电路原因是开关结果是灯泡。你首先要做的是数清楚有哪些开关、哪些灯泡然后才谈得上连接它们。这里有个很实用的小技巧把原因和结果分别用符号标注我习惯用Ci表示原因CauseEi表示结果Effect在纸上列成两组清单。比如“用户名错误”“密码错误”“验证码错误”是原因“提示用户名不存在”“提示密码错误”“允许登录”是结果。列完之后反复比对需求看有没有遗漏的状态。这一步最容易犯的错误是粒度不统一。有人把“输入正确用户名”和“输入正确密码”合并成一个原因“输入正确”导致因果图完全无法表达两个错误同时发生时的优先级逻辑有人又把一个原因的多个细微状态拆得过细比如“密码包含大写字母”“密码包含数字”但这些并不是独立的业务决策条件拆了只会让图爆炸。判断标准很简单在需求逻辑中这个条件是否会被单独判断、单独引发不同结果会——就拆出来不会——就归并或降到数据层面用等价类处理。2.2 因果图的基本符号与约束关系画图前必须掌握的语法因果图有一套标准的符号体系不复杂但每个符号对应一种逻辑关系画之前最好先达成共识。我平时用的最核心的四种关系符号恒等。原因出现结果必出现原因不出现结果也不出现。C1与E1直接连接代表一一对应的逻辑。非。原因出现结果不出现原因不出现结果出现也就是取反。或。几个原因中至少有一个出现结果就出现全部不出现结果才不出现。与。几个原因必须全部出现结果才出现任意一个不出现结果就不出现。除了这四种基本关系因果图里还会用约束条件来表达原因与原因之间、结果与结果之间的限制关系。这些约束在需求里经常被一句带过但恰恰是测试用例最容易覆盖不到的地方。常用的约束符号包括以下几种E互斥。两个原因不会同时成立。比如订单支付方式选“余额支付”和“在线支付”在同一个支付动作中互斥。I包含。多个原因中至少有一个成立。比如“投诉方式”可以通过电话、邮件、在线客服三种渠道至少要选一个。O唯一。多个原因中有且只有一个成立。比如订单状态是新建、已支付、已发货、已完成中的唯一一个。R要求。一个原因出现时另一个原因必须也出现。比如勾选了“同意用户协议”要求“必须勾选”这个原因成立否则不能提交。M屏蔽。一个原因出现时另一个原因就不会出现。比如用户输入了“新密码”旧的“确认密码”输入就被屏蔽或忽略。我把这些约束关系的位置放在原因层因为它们描述的是输入条件彼此间的关系。实际项目中互斥和要求的出现频率最高如果不能准确识别判定表里就会出现无效列。2.3 画图的操作流程与检查要点如何保证因果图不跑偏画因果图的实操步骤我建议按下面的顺序来把提取出的所有原因放在图左侧所有结果放在图右侧。先连接直接、明显的因果关系特别是那些一一对应、直接导致提示或结果的关系。再识别组合关系回头看哪些结果不是单个原因决定而是多个原因组合后才触发的补上与、或逻辑节点。接着标记约束原因之间存在互斥、包含、唯一、要求、屏蔽等关系时在原因之间用约束符号标注。最后走查一遍把图上的原因逐个假设为“出现/不出现”推演结果看是否与需求一致。走查这一步非常关键相当于对需求做了一次逻辑测试。实际工作中我有过这样的经历某个需求描述“用户申请退款时如果订单已发货则退款必须经人工审核”但同一句话里又说“已发货订单不能申请退款”。这两个描述在因果图上同时画出来就是典型的“原因已发货”与结果“允许申请退款”之间出现矛盾。画完图走查时发现这个冲突再去问产品经理对方才承认需求文档这里写错了。这种问题靠通读文档写用例根本不容易发现。还有一点要提醒因果图不是越复杂越好。如果一个图上的原因超过六七个、连线密密麻麻先别急着硬画停下来考虑是不是需求模块太大应该拆成几张图分别处理。因果图的优势在于清晰表达逻辑一旦画到连自己都看不清就失去了意义。3. 从因果图到测试用例判定表转换与用例生成3.1 为什么因果图必须转成判定表而不是直接写用例有段时间我刚接触因果图画完图就迫不及待地开始写用例写了两三条之后发现不对劲因果图表达的是逻辑结构却没有直接给出“有哪些条件组合需要测试”的清单。比如三个原因分别与一个结果有与关系理论上就有2的3次方等于8种条件组合哪些组合是有效的、哪些根本不可能发生因果图只画到了关系层没有展开到组合层。判定表就是用来做这件事的。它把每个原因作为一列条件桩每个条件项的取值设为0或1代表不出现/出现把每个结果作为一列动作桩每一条规则对应一行条件组合和在此组合下的动作取值。判定表天然覆盖了所有逻辑可能并且在化简规则时能挤掉大量重复或矛盾组合。在我看来因果图负责“画逻辑”判定表负责“算组合”少了哪一步都不完整。直接用因果图设计用例往往是凭直觉挑几条组合等于又走回了拍脑袋的老路而直接跳过因果图去写判定表面对复杂需求时又容易理不清逻辑关系画错边的概率大增。先图后表是最稳的路径。3.2 完整案例一个登录验证模块的因果图测试设计实操我拿一个经典但又够典型的登录验证需求来完整走一遍流程。需求描述是这样的用户名、密码、短信验证码均为必填项。当用户名错误时无论密码和验证码是否正确系统都只提示“用户名不存在”。当用户名正确、密码错误时无论验证码是否正确系统都只提示“密码错误”。当用户名和密码均正确、验证码错误时系统提示“验证码错误”。当用户名、密码、验证码全部正确时允许登录。先列原因C1用户名为正确的已注册账号C2密码正确C3验证码正确再列结果E1提示“用户名不存在”E2提示“密码错误”E3提示“验证码错误”E4登录成功这个需求有一个隐藏的优先级用户名错误时后面所有判断都不再看用户名正确但密码错误时验证码判断被跳过。这在因果图上表现为一种“屏蔽”效果本质上就是约束关系中的M屏蔽。根据逻辑关系画因果图C1错误则触发E1。C1正确、C2错误触发E2且此时C3结果被屏蔽不参与判断。C1、C2正确、C3错误触发E3。C1、C2、C3均正确触发E4。转成判定表时三个条件各取0或1理论上共有8条规则。但其中有几个组合因为总逻辑的存在根本不会出现或不会生效比如C1为0用户名错误时C2、C3无论取什么值结果都只有E1。合并后得到的规则如下规则列只列有效逻辑分支规则号C1用户名正确C2密码正确C3验证码正确E1提示用户名不存在E2提示密码错误E3提示验证码错误E4登录成功10--1000210-01003110001041110001这里“-”代表该条件下此因素不影响结果也就是我们在判定表里做规则合并时把无关条件项置为不关心符。这4条规则每条规则对应一条测试用例再用边界值给每个输入条件补上非法数据细节比如用户名不存在但有非法字符、验证码输错一位等最终就能形成一份不错的测试用例集。可能有人会问C1为0、C2为0时真实系统到底是提示“用户名不存在”还是“密码错误”判定的依据是需求中的优先级描述。大多数登录系统的设计是先查用户是否存在用户不存在时根本不会去校验密码所以此时无论密码对不对提示都应该只有“用户名不存在”。但这也是需要和产品确认确认的点测试用例里应明确定义预期结果。3.3 用例覆盖率的取舍如何用最小成本覆盖高价值逻辑设计测试用例时难免会焦虑判定表展开后条件组合太多全测工作量大条件组合太少又怕漏测关键分支。根据经验我一般按三个层次来做取舍。第一层保证每个结果至少被触发一次。像上面案例4种结果都被覆盖到这是底线。第二层保证每个原因的有效和无效状态都至少参与过一次。比如C1覆盖了正确和错误两种状态C2、C3也类似。第三层关注条件组合的边界与异常叠加。这里的“边界”不是数值上的边界而是逻辑上的边界比如“用户名正确、密码正确、验证码正确”这种全通过路径“用户名错误但密码和验证码都正确”这种大量条件同时成立的错误路径。如果条件继续增多判定表的规则数会以2的n次方速度膨胀。这时候不要贪心去测完所有组合而是先结合业务风险给条件分权重。核心业务逻辑、资金相关、权限相关的路径优先全覆盖次要路径可以结合正交实验法用成对组合来压缩用例规模。因果图加判定表的组合拳在“保证不遗漏关键组合”和“控制用例数量爆炸”这两个目标之间能做到一个很好的平衡。4. 常见问题与排查技巧实录4.1 因果图画到一半发现需求本身自相矛盾怎么办这个我在前文提过一嘴但值得单独拿出来细说因为它是因果图实践中最常见、也最有价值的“副作用”。某个电商后台的需求写当订单状态为“已发货”时用户可以申请退款另一个地方又写申请退款时校验订单状态若为“已发货”则提示不能申请。两个描述放在因果图上原因C1“订单已发货”与结果E1“允许退款”的关系一张图里又画恒等又画非直接冲突。遇到这种情况千万不要自己拍板选一个解释去画图。正确做法是把矛盾点标记出来整理成问题清单发给产品经理或需求方确认。很多时候这类矛盾是需求文本在不同章节由不同人撰写造成的确认后往往会改需求或者判定测试的预期结果这些都必须有明确的结论。因果图在这里的真正作用是成为和产品沟通的公共语言双方看着图讨论比对着文字掰扯效率高得多。4.2 条件太多导致组合爆炸怎么拆解才高效当原因数量超过六七个、且彼此之间约束少的时候判定表规则数会迅速膨胀到几十上百条。这时候硬啃因果图效率很低我的处理方式是先拆模块、再分层、后过滤。先说拆模块。如果一个支付流程同时涉及支付方式、商品类型、用户等级、优惠券、库存状态等多个维度先不要试图画一张大而全的因果图而是按业务阶段拆创建订单阶段的规则、支付阶段的规则、支付成功回调阶段的规则分别画图、分别转表。阶段之间只保留必要的状态传递不把跨阶段的条件全部混在一张图里。再说分层。区分哪些条件是决定功能流程是否走下去的关键条件哪些条件只是影响某个字段显示或某个参数取值。关键条件决定主干逻辑必须进因果图字段显示类的可以用等价类加界面校验表来处理。最后说过滤。判定表转出来以后逐列检查有没有违反约束的无效组合比如E约束下两个原因同时为1、O约束下允许了多个1的列这些列可以直接删掉。综合用这几个办法绝大多数项目的用例数量能控制在可接受范围。4.3 从因果图转判定表时最容易踩的几个坑这个环节我踩过的坑不少挑三个最典型的说说。第一个坑把“与”关系误划成“或”关系或者反过来。原因一般在图形上看起来差不多但转换到判定表与关系的规则行只有一个组合是1或关系则有多行是1一旦这里画错结果预测全错。后来我习惯在画完图后把每个结果对应的原因关系用逻辑表达式写一遍比如E4 C1 AND C2 AND C3作为转表的对照基准。第二个坑因果图上的约束关系没有落到判定表里。比如两个原因之间画了E约束但转判定表时还是把所有组合都列出来表格里会出现“用户名正确且用户名错误”同时为1这种物理上不可能的规则。约束关系就是判定表的过滤条件转表之后必须做一遍约束校验。第三个坑规则合并时把不同动作的规则强行合到一列。规则合并只能针对结果完全相同、条件中存在无关项的规则如果结果不同即便条件项再接近也不能合并。比如“用户名错误”和“密码错误”如果提示信息不同即使某个组合下条件项只有一个不同也绝不能合并成一条规则否则输出动作对不上。4.4 画图工具和辅助手段怎么选更顺手工具层面我没什么执念用过Visio、ProcessOn、draw.io也直接在纸上画过。线上协作项目比较多时我习惯用ProcessOn或draw.io好处是团队成员能直接看图提意见评审时不用把图截来截去。如果公司有内网的文档系统很多也自带画图能力直接用就行。真正提升效率的辅助手段是用Excel或在线表格把判定表的生成半自动化。原因数量多的时候手工展开所有条件组合很容易漏。我个人的做法是先在表格里建一个二进制组合生成区把n个条件的全部取值组合用数学上的二进制展开方式列出来然后结合因果图上的逻辑关系写对应公式自动算出每个结果的动作值。比如C1对应的单元格填IF公式判断输入值E1对应的单元格参照逻辑表达式返回0或1。这样能快速生成完整判定表再手动删掉无效组合比纯手工快很多。写脚本也行但大多数项目用Excel公式足够没必要为了画因果图专门写程序。写在最后的实操心得关于因果图分析法我个人的体会是它看着像一种画图技巧本质上是一种强制性的逻辑训练。每次画完一张因果图我都能对这个业务模块的逻辑关系有更深的理解这是单纯照需求写用例给不了的。尤其是那种规则相互嵌套、异常分支极多的模块因果图法几乎就是测试用例设计的定海神针。最后再分享一个小技巧在实际项目中不要等到测试设计阶段才开始画因果图。需求评审阶段只要看到复杂的条件组合描述就当场在笔记本上画一个简化版的因果图草稿往往能立刻发现问题把矛盾消灭在评审环节。这比等到用例设计阶段再发现需求问题要省太多事了。
返回列表