3. 测试用例设计方法:等价类划分、边界值分析、因果图法在嵌入式场景的应用

嵌入式测试,说白了就是跟有限的资源和苛刻的环境打交道。你想想看,一个跑在MCU上的程序,Flash就那么大,RAM更是抠着用,测试用例要是设计得不好,要么测不全,要么测到死机。今天我就把我在几个量产项目里摸爬滚打的经验,跟大伙儿聊聊这三种最实用的用例设计方法。

3.1 等价类划分:别在同一个坑里摔三次

等价类划分的核心思想很简单:把输入域分成若干个子集,每个子集里挑一个代表值来测。为什么?因为同一个等价类里的值,程序处理逻辑是一样的。你测了100个有效值,不如测1个有效值加1个无效值来得实在。

核心原则:每个等价类至少覆盖一次,无效等价类要单独测。

我在一个车载传感器项目中遇到过这么个事:一个温度采集模块,输入范围是 -40°C 到 125°C。测试小哥写了50个用例,从 -40 到 125 每隔几度测一次。我说你停,这50个用例其实只覆盖了1个有效等价类。真正该测的是:

  • 有效等价类:-40 到 125 之间的任意值(比如 25°C)
  • 无效等价类(低于下限):比如 -50°C
  • 无效等价类(高于上限):比如 130°C

你看,3个用例就覆盖了50个用例的测试效果。这就是等价类划分的威力。

我的习惯:先列所有输入条件,再画等价类表。有效等价类一般只有一个,无效等价类可能有多个(空值、超范围、非法格式等)。

3.2 边界值分析:Bug最爱藏在边界上

为什么边界值这么重要?因为程序员写判断条件时,最容易在边界上犯迷糊。比如 if (temp >= -40 && temp <= 125),你写的是 >= 还是 >?差一个等号,天差地别。

边界值分析的基本套路:取每个等价类的边界值,以及边界值两侧的邻值。

边界类型 取值 说明
下边界 -40 刚好在范围内
下边界-1 -41 刚好低于范围
上边界 125 刚好在范围内
上边界+1 126 刚好高于范围

我曾经在一个步进电机驱动项目里,就因为边界值没测全,导致电机在极限位置抖动。原因是位置计数器用了 uint16_t,最大值 65535,当计数到 65535 时再加 1 就溢出了。边界值分析如果覆盖了 65534、65535、0、1 这几个点,这个问题当场就能发现。

注意:嵌入式里除了数值边界,还有时间边界、缓冲区边界、状态机边界。比如看门狗超时时间、串口FIFO深度、任务调度周期,这些都要做边界值分析。

3.3 因果图法:多条件组合的逻辑迷宫

等价类和边界值主要处理单输入条件。但嵌入式系统里,很多功能是多个条件组合触发的。比如:

  • 刹车踩下 && 车速 > 0 → 点亮刹车灯
  • 刹车踩下 && 车速 == 0 && 档位在P挡 → 不点亮刹车灯(节能逻辑)

这种多条件组合,用因果图法最合适。因果图的核心是:原因(输入条件)→ 中间节点(逻辑组合)→ 结果(输出动作)。

我建议你按这个步骤来:

  1. 列出所有原因(输入条件):比如刹车踩下、车速 > 0、档位在P挡
  2. 列出所有结果(输出动作):比如点亮刹车灯、不点亮刹车灯
  3. 画出因果图:用与门、或门、非门连接原因和结果
  4. 转成判定表:把因果图转成真值表,每一列是一个测试用例
  5. 简化判定表:合并冗余列,减少用例数量

下面是我画的一个简化版因果图,展示刹车灯控制逻辑:

刹车灯控制因果图 原因A: 刹车踩下 原因B: 车速 > 0 原因C: 档位在P挡 中间1: A && B 中间2: A && !B && C 结果1: 点亮刹车灯 结果2: 不点亮刹车灯 说明: 中间1 = 刹车踩下 且 车速>0 → 点亮刹车灯 中间2 = 刹车踩下 且 车速=0 且 档位在P挡 → 不点亮刹车灯(节能逻辑) 其他组合:刹车未踩下 → 不点亮刹车灯(默认状态)

画完因果图,下一步就是转成判定表。判定表的每一列就是一个测试用例。我一般用这个模板:

用例编号 原因A: 刹车踩下 原因B: 车速 > 0 原因C: 档位在P挡 预期结果
TC-01 1 1 0 点亮刹车灯
TC-02 1 0 1 不点亮刹车灯
TC-03 1 0 0 点亮刹车灯
TC-04 0 1 0 不点亮刹车灯
TC-05 0 0 1 不点亮刹车灯
TC-06 0 0 0 不点亮刹车灯

我的经验:因果图法在嵌入式里特别适合测状态机、安全互锁逻辑、多传感器融合决策。但要注意,条件太多时判定表会爆炸(2^n)。我一般控制在4-6个条件,超过这个数就拆成子功能测。

3.4 三种方法的嵌入式实战组合

实际项目中,这三种方法不是孤立的。我一般这样组合:

  • 第一步:等价类划分——先把所有输入条件分类,确定有效和无效范围
  • 第二步:边界值分析——在每个等价类的边界上补充用例
  • 第三步:因果图法——对多条件组合逻辑,画因果图、转判定表

举个例子,一个温控器项目:

  • 输入:温度值(-20~80°C)、模式选择(加热/制冷/自动)、定时时间(0~720分钟)
  • 输出:继电器通断、LED指示灯、蜂鸣器报警

用等价类划分:温度分有效类(-20~80)和两个无效类(<-20、>80)。模式分三个有效类。时间分有效类(0~720)和两个无效类。

用边界值分析:温度边界取 -21、-20、80、81。时间边界取 -1、0、720、721。

用因果图法:比如“温度 > 75 且 模式为加热 → 蜂鸣器报警并关闭继电器”。这个组合逻辑用因果图一画,判定表一列,测试用例就全了。

我曾经踩过的坑:在一个RTOS任务调度测试里,我只用了等价类和边界值,漏掉了“高优先级任务 && 低优先级任务持有互斥锁”这个组合。结果高优先级任务一直等锁,低优先级任务被抢占,死锁了。这就是因果图没做全的后果。

3.5 嵌入式场景的特殊考量

嵌入式测试用例设计,跟纯软件测试有几个不一样的地方:

考量点 说明 用例设计建议
资源受限 RAM/Flash有限,用例不能太多 优先用边界值和因果图,减少冗余等价类
实时性 响应时间必须在规定窗口内 边界值要覆盖时间边界(如中断响应时间)
硬件耦合 软件行为依赖硬件状态 因果图里要把硬件状态作为原因节点
状态机 系统在不同状态下的行为不同 每个状态都要做等价类和边界值分析

嗯,说到状态机,我再多提一句。嵌入式系统里到处都是状态机:通信协议状态、设备初始化状态、任务调度状态。每个状态下的输入条件都不一样,所以因果图法在状态机测试里特别好用。我习惯先画状态转换图,再对每个状态单独画因果图。

总结一下:等价类划分帮你减少用例数量,边界值分析帮你抓住最容易出Bug的地方,因果图法帮你理清多条件组合逻辑。三者结合,嵌入式测试用例的质量就能上一个台阶。