3. 控制逻辑测试需求分析

系统需求通常以自然语言描述整车或子系统应实现的功能,例如“当车速大于 30 km/h 且驾驶员未踩制动踏板时,车门应保持锁止”。这类需求面向功能行为,而 Stateflow 测试需求必须落到状态、迁移、事件、条件与动作上,才能被测试用例直接覆盖。二者之间的鸿沟,正是本节要解决的核心问题:如何把一条系统需求,稳定地分解为可执行、可追踪、可判定的 Stateflow 测试需求。

一、分解的基本路径:从功能语句到状态机要素

分解不是简单地把一句话拆成几句,而是沿着“功能语义 → 状态变量 → 迁移条件 → 输出动作 → 边界与异常”这条链路逐层落地。以车门锁止需求为例,第一步识别功能主体与触发条件:主体是“车门锁止状态”,触发条件是“车速 > 30 km/h”与“制动踏板未踩下”的逻辑与关系。第二步确定状态集合:至少存在 Locked 与 Unlocked 两个状态,可能还有 Transitioning 中间态。第三步把条件映射为迁移守卫:v > 30 && brake == 0 触发 Unlocked → Locked,v <= 30 || brake == 1 触发 Locked → Unlocked。第四步明确动作:进入 Locked 时置 lockCmd = 1,进入 Unlocked 时置 lockCmd = 0。第五步补充边界与异常:车速恰好等于 30 km/h 时属于哪一侧、传感器信号无效时保持还是回退,这些都必须写成独立测试需求,否则测试用例无法判定期望结果。

分解口诀(示例):一条系统需求 → 状态集合 → 迁移对(源/目标)→ 守卫条件 → 动作输出 → 边界值 → 异常分支。每一步都产生一条或多条可独立验证的测试需求。

二、需求可测试性准则

分解出的测试需求若不可测试,后续用例设计就是空中楼阁。可测试性至少满足以下准则:

  • 可观测:每条需求必须对应一个可观测的输出、状态或信号,例如 lockCmd、状态机当前状态、日志标志位。无法观测的需求应改写或补充观测点。
  • 可判定:期望结果必须唯一且可比较,避免“应正常工作”“应合理响应”这类模糊表述。应写成“在 t+100 ms 内 lockCmd 由 0 变为 1”。
  • 可触发:输入条件必须能在测试环境中构造,包括边界值、非法值和时序组合。若某条件无法注入,则该需求不可测。
  • 原子性:一条测试需求只验证一个逻辑点,避免“与”“或”混合导致失败时无法定位。复合条件应拆为多条需求或明确组合覆盖策略。
  • 无歧义:时间、单位、优先级、默认值必须明确。例如“车速大于 30”应写为“车速 > 30 km/h(采样周期 10 ms)”。

可测试性检查可在需求评审阶段用一句话自检:“我能否写出一个输入序列,并明确说出在什么时刻、观察哪个变量、得到什么值,就算通过?”若不能,该需求需要重写。

三、需求追踪矩阵的建立

追踪矩阵是分解工作的“账本”,用于回答三个问题:每条系统需求被哪些测试需求覆盖?每条测试需求对应哪个 Stateflow 状态或迁移?测试用例又覆盖了哪些测试需求?建议矩阵至少包含以下字段:系统需求 ID、系统需求描述、测试需求 ID、测试需求描述、对应状态/迁移、输入条件、期望输出、覆盖类型(正常/边界/异常)、用例 ID、覆盖状态。

建立时遵循“双向可追”原则:从系统需求向下能找到测试需求与用例,从任一测试需求向上能回溯到系统需求。对于 Stateflow 模型,可在状态和迁移上附加需求链接(如 Simulink Requirements 的链接),使矩阵与模型同步。若某条系统需求没有对应测试需求,说明分解遗漏;若某条测试需求无法回溯系统需求,说明存在过度测试或需求蔓延。

系统需求 → Stateflow 测试需求分解与追踪 系统需求层 SR-01 车速>30 且未制动 → 车门应锁止 (自然语言,功能行为) 分解 Stateflow 测试需求层 TR-01 正常:v=35, brake=0 TR-02 边界:v=30, brake=0 TR-03 异常:brake 信号无效 (状态/迁移/条件/动作) 映射 Stateflow 模型要素 状态:Unlocked / Locked 迁移守卫:v>30 && !brake 动作:lockCmd = 1 (可链接、可覆盖) 需求追踪矩阵(示例) 系统需求 测试需求 对应状态/迁移 输入条件 期望输出 覆盖 SR-01 TR-01 正常 Unlocked→Locked v=35, brake=0 lockCmd=1 ✓ SR-01 TR-02 边界 Unlocked→Locked v=30, brake=0 lockCmd=0(不迁移) 待定 SR-01 TR-03 异常 Locked 保持 brake 信号无效 lockCmd 保持原值 待定 SR-02 TR-04 正常 Locked→Unlocked v=20, brake=0 lockCmd=0 ✓ SR-02 TR-05 边界 Locked→Unlocked v=30, brake=1 lockCmd=0 ✓ 覆盖状态:✓ 已覆盖 待定 需补充用例或明确期望值

四、分解中的常见陷阱与处理

第一类陷阱是“条件合并过度”。把“车速大于 30 且未制动”与“车速大于 30 且制动”合并成一条测试需求,会导致边界判定失效。处理方式是按条件组合拆分,并明确每个组合的期望状态。第二类陷阱是“忽略时序”。Stateflow 是事件驱动的,迁移可能在同一采样周期内多次触发,测试需求必须写明事件顺序与采样周期,例如“在 10 ms 周期下,连续 3 个周期满足条件后迁移”。第三类陷阱是“默认迁移未覆盖”。若状态机存在默认迁移或历史节点,测试需求应包含上电初始化、复位后行为等场景,否则覆盖不完整。

第四类陷阱是“追踪矩阵只建不维护”。模型迭代后,状态或迁移被重命名、删除,矩阵若不同步更新,追踪关系就会断裂。建议将矩阵与模型链接绑定,并在每次模型变更后执行一次“需求覆盖检查”:统计未被任何测试需求覆盖的系统需求数量、未被任何用例覆盖的测试需求数量,以及无法回溯系统需求的测试需求数量。这三个指标能快速暴露分解质量。

注意:追踪矩阵不是一次性文档,而是随模型演进的活账本。若某条测试需求在矩阵中找不到对应状态或迁移,通常意味着分解粒度过粗或模型实现缺失,需要回到分解步骤重新对齐。

五、一个可复用的分解检查清单

在实际项目中,可按以下顺序逐条检查:系统需求是否已识别全部触发条件与输出?每个条件是否已映射到具体状态或迁移?边界值(等于、略大于、略小于)是否已单独成条?异常与无效信号是否有明确处理策略?每条测试需求是否可观测、可判定、可触发?追踪矩阵是否双向可追?覆盖状态是否已标注?完成这七项检查后,分解结果即可进入用例设计阶段,后续的测试用例将直接以测试需求 ID 为索引,形成从系统需求到 Stateflow 模型再到测试执行的完整链路。