测试序列基础与 Stateflow 图调度输入
1. 概念讲解
1.1 什么是测试序列
测试序列由按层次排列的测试步骤(test step)组成。你用它来定义两类内容:一是测试输入——在每个步骤里给被测系统施加什么信号;二是测试如何推进——在什么条件下结束当前步骤、跳到下一步骤。每个测试步骤包含两部分:动作(actions)在步骤开始执行时运行一次;转移(transitions)定义该步骤何时停止、哪个步骤接着执行。动作与转移都使用 MATLAB 作为动作语言。测试序列通过 Test Sequence 模块和 Test Sequence Editor(测试序列编辑器,第 13 讲详讲)创建。
1.2 层次结构(Test Sequence Hierarchy)
Test Sequence 模块中的测试步骤可以有父步骤(parent step)与子步骤(substep)。子步骤只有在父步骤处于激活状态时才可能激活。同一层次上的一组步骤共享同一种转移类型;当你新建一个测试步骤时,它会自动成为同组其他步骤的一个可选的"下一步骤(Next Step)"目标。这种父子层次使得你可以把一个复杂工况拆成"加速→巡航→减速"这样的结构化段落,而不是把所有步骤平铺在一层。
1.3 测试序列场景(Test Sequence Scenarios)
在一个 Test Sequence 模块中可以定义多条测试序列,这些序列称为测试序列场景(test sequence scenarios)。场景的价值在于:不必在测试框架里摆放多个 Test Sequence 模块,就能在同一个框架中定义多组不同的测试序列。运行场景的方式有:
在 Test Sequence Editor 中激活单个场景,然后运行模型;
用 API 命令激活单个场景,然后运行模型;
用一个工作区变量控制当前激活的场景,然后运行模型;
用自定义测试脚本在运行模型时循环遍历多个场景;
在测试管理器(Test Manager)中定义测试迭代(iterations),使一个测试用例运行多个场景。
场景的深入用法与编程方式见指南 3-60、3-63 节(本课程第 16 讲前后)。
1.4 两种转移类型(Transition Types)
Test Sequence 模块中的步骤之间通过两种方式推进:
标准转移(Standard transition):你定义一串动作,按仿真条件反应。标准转移序列从第一个步骤开始,依据转移条件与"下一步骤"列设定逐段推进。它适合"按时间或事件顺序走完一个工况"的测试流程。下图是一个典型的标准转移序列:四个步骤分别把布尔输出
RedButtonIn、GreenButtonIn置为不同组合,每个步骤激活 1 秒后通过after(1,sec)转移到下一步,最后到达EndTest。
When 分解(When decomposition):When 分解序列类似于程序设计中的
switch语句——序列根据模型中发生的特定条件来动作。在 When 分解序列中,步骤依据你在步骤名之后定义的条件来激活,步骤之间不使用转移。下图是一个 When 分解:三个子步骤分别在gear等于 1、2、3 时激活,并各自执行一条verify语句;最后的Else子步骤没有动作,用来兜底不匹配任何 when 条件的仿真工况。
When 分解在评估中极其常用,第 11 讲会专门用它来编写评估逻辑。
1.5 用 Stateflow 图做测试框架调度与信号源
除 Test Sequence 模块外,你还可以用MATLAB Function 模块或Stateflow 图(Stateflow Chart)来定义测试框架的调度。使用 Stateflow 图的好处是可以用到 Test Sequence 模块和 MATLAB Function 模块都不具备的 Stateflow 特性,例如Stateflow 变体(variants)、图形函数(graphical functions)、超转移(super transitions)与超步(super steps)。借助 Stateflow 变体,你可以在同一个测试框架里指定多个测试场景。反过来,如果你不需要多场景或复杂序列逻辑,就应该用 Test Sequence 模块——它的测试调度语法更简单。
注意:使用 Stateflow 图做测试框架输入或调度,必须持有 Stateflow 许可。
Stateflow 图在测试框架中可扮演三种角色:
作为调度器(Scheduler):要把 Stateflow 图用作测试框架的调度器,被测模型或子系统必须至少有一个函数调用信号(function-call signal)。Stateflow 状态承担与 Test Sequence 模块中序列步骤相同的角色,转移定义从一个状态迁移到另一个状态的判据。下图是一个以 Chart 为调度器的测试框架:图中新增了一个名为Simulink Function scheduler的 Chart,由它向
send_fcn函数调用输出触发事件。
作为信号源(Source):创建测试框架时在 Sources and Sinks 区把源从 Inport 换成 Chart,图便会被加入测试框架。下图中 Chart 作为信号源直接驱动被测子系统
Subsys1。
同时作为调度器与信号源(Scheduler and Source):指南以
sltest_autosar_chart.slx(汽车油门位置控制器的 AUTOSAR 组合模型)为例演示了这一用法。AUTOSAR 组合模型由若干相互连接的 Model 块组成,每个块代表一个原子 AUTOSAR 软件组件(ASWC);Simulink 输入输出端口对应 AUTOSAR 端口,信号线对应组件连接器。主副油门位置输入用外部时序输入建模,直接透过 Chart 馈送而不修改——这种建模方式在"部分激励可建模、部分只能用外部采集数据"时很有用。
2. 操作步骤 / 工作流
用 Stateflow 图作为调度器:
在模型或子系统上右键,分别选择Test Harness > Create for Model或Create for <subsystem>。
在 Create a Test Harness 对话框中:
对模型:把Add scheduler for function-calls and rates设为Chart;
对子系统:把Generate function call signals设为Chart。 测试框架中会新增一个名为Simulink Function scheduler的 Chart。
打开该 Stateflow 图,用 Stateflow 状态、转移等对象定义测试序列。
编程方式:把
sltest.harness.create的SchedulerBlock属性设为'Chart'。
用 Stateflow 图作为信号源:
同样右键创建测试框架。
在 Create Test Harness 对话框的Sources and Sinks区,把源下拉框从 Inport 改为Chart。
打开 Chart,用 Stateflow 逻辑定义测试框架信号源。
编程方式:把
sltest.harness.create的Source属性设为'Chart'。
用单个 Chart 同时做调度器与信号源(以 sltest_autosar_chart 为例):
打开模型:
open_system('sltest_autosar_chart')(示例测试框架已预先建好,无需重建)。在编辑器画布右下角用视角控制(perspective control)单击Internal Test Harness,打开已建好的测试框架。
双击测试框架中的 Chart,查看调度逻辑:被测组件(AUTOSAR 模型)需要油门踏板位置传感器输入
APP_HwIO_Value,由图中三个状态建模——Initialize状态把输入置为标称值 170;Run状态模拟持续 950 ms 的稳态加速指令;Terminate状态把加速指令复位回标称值。被测组件采用导出函数建模风格(export-function modeling style)。测试框架创建时,其 Stateflow 图被配置为调用每个根级 Simulink Function 块,并向模型中每个函数调用子系统发送触发事件;本示例中,发送触发事件的代码位于各状态生成激励波形之后。
在测试框架中运行模型,打开测试框架中的 Scope 查看油门指令输出。
3. 示例
% 打开 AUTOSAR 组合示例模型 open_system('sltest_autosar_chart'); % 编程方式创建测试框架:以 Chart 作为信号源 sltest.harness.create('modelName', 'Source', 'Chart'); % 编程方式创建测试框架:以 Chart 作为函数调用调度器 sltest.harness.create('modelName', 'SchedulerBlock', 'Chart');下图是 Create Test Harness 对话框中把源与调度器都设为 Chart 的位置(红框标出两处下拉框)。
下图是打开后的测试框架:左侧 Chart 同时生成激励并调度各*_Run_0.005函数调用,右侧 Scope 观察ThrCmd_HwIO_Value。
下图是 Chart 内部的三个状态:Initialize / Run / Terminate,每个状态内既给APP_HwIO_Value赋值,又用send(...)向各 ASWC 的运行入口发送触发事件,状态之间用after(0.05,sec)、after(0.95,sec)迁移。
4. 要点与注意事项
测试步骤的动作在步骤开始时执行一次;转移条件每步都在仿真中求值,满足条件才迁移。
子步骤只能在父步骤激活时激活;同组步骤共享转移类型,新建步骤自动出现在同组"下一步骤"下拉框中。
一个 Test Sequence 模块可含多个场景,避免在框架里堆多个模块;场景可通过编辑器、API、工作区变量、自定义脚本循环、测试迭代五种方式激活。
标准转移序列适合"按顺序走工况";When 分解适合"按当前工况条件做评估",二者不要混用在同一父步骤下。
用 Stateflow 图做调度的硬性前提:被测模型/子系统至少有一个函数调用信号;并需 Stateflow 许可。
能不用 Stateflow 图就不用:Test Sequence 模块语法更简单;只有当需要 Stateflow 变体、图形函数、超转移、超步等复杂调度时才升级到 Chart。
编程入口:
Source属性与SchedulerBlock属性分别控制信号源与调度器的类型。