4、测试用例设计方法:等价类划分、边界值分析、因果图法、场景法在HIL中的应用
做HIL测试这么多年,我见过太多人一上来就闷头写用例。结果呢?要么测不全,要么重复测。说白了,测试用例设计不是拍脑袋,得有章法。今天我就把这四种最实用的方法掰开揉碎讲给你听。
4.1 等价类划分:别做无用功
等价类划分,核心思想就一句话:把输入域分成若干类,每类只测一个代表。为什么?因为同一类里的数据,程序处理逻辑是一样的。
我在项目中遇到过这样一个案例:测试BMS的SOC(荷电状态)信号。输入范围是0%到100%,步长0.5%。如果每个值都测,要测201个点。但用等价类划分,我只测了5个点就搞定了。
等价类划分在HIL中的典型应用:
- 有效等价类:正常范围内的输入值
- 无效等价类:超出范围、格式错误、空值等
举个例子,测试一个车速传感器信号:
// 等价类划分示例 - 车速信号测试
// 输入范围:0 ~ 250 km/h,分辨率0.1 km/h
有效等价类:
- 低速区:0 ~ 30 km/h(停车、蠕行工况)
- 中速区:30 ~ 80 km/h(城市工况)
- 高速区:80 ~ 120 km/h(高速工况)
- 极速区:120 ~ 250 km/h(极限工况)
无效等价类:
- 负值:-1 km/h
- 超上限:251 km/h
- 非数值:字符串、特殊字符
你想想看,每个区间选一个代表值就够了。比如低速区选15 km/h,高速区选100 km/h。这样既覆盖了所有逻辑分支,又省了80%的测试时间。
我的小技巧:等价类划分时,别忘了考虑「边界值」——这俩方法经常搭配使用。我习惯先划等价类,再在边界上补几个用例。
4.2 边界值分析:Bug最爱藏在哪儿?
经验告诉我,80%的Bug都藏在边界上。为什么?因为开发写代码时,最容易在判断边界条件时犯迷糊。比如「if (x >= 100)」还是「if (x > 100)」,差一个等号就是天壤之别。
边界值分析的原则很简单:取边界值、边界值+1、边界值-1。嗯,就这么简单,但效果出奇的好。
| 边界类型 | 测试值 | 说明 |
|---|---|---|
| 下边界 | 0, 1, -1 | 最小值及其邻域 |
| 上边界 | 250, 249, 251 | 最大值及其邻域 |
| 内部边界 | 30, 29, 31 | 区间切换点 |
我曾经踩过一个坑:测试一个温度传感器,范围是-40°C到125°C。我测了-40、125、0、50这些值,全过了。结果呢?现场反馈说温度到-41°C时系统直接死机。后来一查,代码里写的是「if (temp < -40)」,但ADC转换精度导致-40.1°C被截断成了-41。从那以后,我每个边界值都会多测一个「边界值±分辨率」。
注意:HIL测试中,边界值分析不光用于输入信号,也用于输出信号的判断阈值。比如故障诊断的触发阈值、保护机制的激活阈值,这些地方最容易出问题。
4.3 因果图法:理清复杂逻辑
因果图法,说白了就是画一张「原因→结果」的关系图。当系统有多个输入条件,且它们之间存在组合逻辑时,这方法特别好用。
我记得有一次测试VCU的扭矩分配逻辑。输入条件有5个:车速、油门开度、制动信号、档位、电池SOC。输出结果有3种:驱动扭矩、制动扭矩、滑行扭矩。如果直接排列组合,要测2^5=32种情况。但用因果图一分析,很多组合是无效的,实际只需要测12种。
因果图法的步骤:
- 列出所有原因(输入条件):比如车速>0、油门>0、制动有效等
- 列出所有结果(输出动作):比如输出驱动扭矩、输出制动扭矩等
- 画出因果关系:用与、或、非等逻辑连接
- 生成决策表:把因果图转成表格,每列是一个测试用例
因果图法在HIL中的典型场景:
- 故障诊断逻辑(多个故障同时发生时,优先级怎么定?)
- 模式切换逻辑(运动模式、经济模式、雪地模式)
- 安全保护逻辑(多个条件同时满足才触发保护)
举个例子,一个简单的制动优先逻辑:
原因:
C1: 车速 > 5 km/h
C2: 油门开度 > 0%
C3: 制动踏板被踩下
结果:
E1: 输出驱动扭矩
E2: 输出制动扭矩
E3: 扭矩清零
逻辑关系:
IF (C1 AND C2 AND NOT C3) THEN E1
IF (C1 AND C3) THEN E2
IF (C1 AND C2 AND C3) THEN E3 // 制动优先
你看,用因果图一梳理,逻辑关系一目了然。测试用例也自然就出来了。
4.4 场景法:模拟真实工况
前面几种方法都是「点」上的测试。但HIL测试最终要回答的问题是:系统在实际场景中能不能正常工作?这就需要场景法了。
场景法,说白了就是编故事。把用户的操作流程、系统的响应过程串成一个完整的故事。每个故事就是一个测试场景。
我习惯把场景分为两类:
- 基本流:正常操作,系统按预期工作
- 备选流:异常操作,系统如何处理?
举个例子,测试一个自动紧急制动(AEB)系统:
场景1:基本流 - 前车减速,AEB正常触发
1. 自车以60 km/h巡航
2. 前车以40 km/h行驶,距离50m
3. 前车突然减速到20 km/h
4. AEB计算碰撞时间TTC < 2.6s
5. 系统发出警告,并施加部分制动
6. TTC < 1.2s,系统施加全力制动
7. 车辆安全停止,与前车保持安全距离
场景2:备选流 - 驾驶员干预
1-4步同上
5. 系统发出警告后,驾驶员主动打方向盘变道
6. AEB检测到驾驶员干预,退出制动
7. 车辆正常变道通过
场景3:备选流 - 目标丢失
1-4步同上
5. 前车突然变道离开本车道
6. AEB检测到目标丢失,取消制动
7. 车辆恢复正常行驶
你想想看,一个AEB系统,如果只测基本流,那肯定不够。实际路上什么情况都可能发生。我一般每个功能至少设计3-5个备选流,覆盖常见的异常情况。
我的经验:场景法设计用例时,多跟系统工程师聊聊。他们最清楚用户在实际使用中会遇到什么问题。我曾经跟一个老司机聊了半小时,就挖出了3个我之前完全没想到的测试场景。
4.5 四种方法的搭配使用
说了这么多,你可能要问:这四种方法到底怎么选?我的建议是:别单选,要组合。
| 测试阶段 | 推荐方法 | 用途 |
|---|---|---|
| 功能验证 | 等价类 + 边界值 | 快速覆盖基本功能 |
| 逻辑验证 | 因果图法 | 覆盖复杂逻辑组合 |
| 系统验证 | 场景法 | 模拟真实工况 |
| 回归测试 | 全部方法 | 确保修改不引入新Bug |
我个人习惯的流程是这样的:先用场景法画出主要测试场景,再用因果图法分析场景中的逻辑分支,然后用等价类划分和边界值分析填充具体的测试数据。这样既有宏观的场景覆盖,又有微观的数据覆盖,测试质量才有保障。
最后提醒一句:方法再好,也要落地。我见过有人把等价类划分得天花乱坠,结果测试时发现硬件接口都不对。所以,设计用例前,先确认你的HIL台架能不能支持这些测试场景。别纸上谈兵。