创建和执行测试用例
此示例展示如何使用 Simulink® Design Verifier™ 函数记录输入信号、创建框架模型、生成缺失覆盖率的测试用例、合并框架模型以及执行测试用例。
该示例首先将输入信号记录到其父模型中实现控制器的组件,然后根据记录的数据为控制器创建框架模型。您使用 Simulink Design Verifier 来查找实现缺失覆盖率的新测试用例。然后将第一个框架模型与Simulink Design Verifier分析后生成的框架模型合并。最后,您捕获所有测试用例并在仿真模式和软件在环 (SIL) 模式下使用这些测试用例执行控制器,然后使用 CGV API 比较结果。
检查产品可用性
此示例需要有效的 Stateflow ® 许可证。为了演示软件在环 (SIL) 模式下的测试执行,它还需要有效的 Simulink® Coder™ 和 Embedded Coder ™ 许可证。
if ~license('test','Stateflow') return; end canUseSIL = license('test','Real-Time_Workshop') && ... license('test','RTW_Embedded_Coder');
将输入信号记录到组件并创建框架模型
slvnvdemo_powerwindow
模型包含一个电动车窗控制器和一个低阶对象模型。组件slvnvdemo_powerwindow/power_window_control_system/control
是一个引用模型slvnvdemo_powerwindow_controller
的Model模块,该模型使用Stateflow®图表实现控制器。
要使用仿真工厂模型中的控制器的信号为控制器创建框架模型,首先记录输入信号,然后使用记录的数据调用框架生成。
open_system('slvnvdemo_powerwindow'); load_system('slvnvdemo_powerwindow_controller'); loggedSignalsPlant = ... sldvlogsignals('slvnvdemo_powerwindow/power_window_control_system/control'); harnessModelFilePath = ... sldvmakeharness('slvnvdemo_powerwindow_controller',loggedSignalsPlant); [~,harnessModel] = fileparts(harnessModelFilePath);
### Searching for referenced models in model 'slvnvdemo_powerwindow_controller'. ### Found 1 model references to update. ### Starting serial model reference simulation build. ### Successfully updated the model reference simulation target for: slvnvdemo_powerwindow_controller Build Summary Simulation targets built: Model Action Rebuild Reason ============================================================================================================================= slvnvdemo_powerwindow_controller Code generated and compiled. slvnvdemo_powerwindow_controller_msf.mexa64 does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 19.616s ### Searching for referenced models in model 'slvnvdemo_powerwindow'. ### Found 1 model references to update. ### Starting serial model reference simulation build. ### Model reference simulation target for slvnvdemo_powerwindow_controller is up to date. Build Summary 0 of 1 models built (1 models already up to date) Build duration: 0h 0m 0.4686s ### Searching for referenced models in model 'slvnvdemo_powerwindow_controller'. ### Found 1 model references to update. ### Starting serial model reference simulation build. ### Successfully updated the model reference simulation target for: slvnvdemo_powerwindow_controller Build Summary Simulation targets built: Model Action Rebuild Reason ================================================================================ slvnvdemo_powerwindow_controller Code generated and compiled. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 13.945s
使用记录信号测量覆盖范围
使用 cvtest
和 cvsim
函数来测量控制器模型slvnvdemo_powerwindow_controller
以及框架模型中捕获的记录信号所实现的模型覆盖率。
cvhtml
函数生成一份报告,表明通过仿真从闭环模型捕获的测试用例,实现了 40% 的决策覆盖率、35% 的条件覆盖率和 10% 的 MCDC覆盖率。
test = cvtest(harnessModel); test.modelRefSettings.enable = 'On'; test.modelRefSettings.excludeTopModel = 1; covDataFromLoggedSignals = cvsim(test); cvhtml('Coverage with Logged Test Cases',covDataFromLoggedSignals);
查找缺失覆盖的测试用例
在测试生成期间使用现有覆盖率数据之前,必须将数据保存到覆盖率数据文件 (.cvt) 中。您可以通过在覆盖率数据文件参数中指定覆盖率数据路径,并在Simulink Design Verifier配置参数的测试生成窗格中将忽略现有覆盖率数据中满足的目标参数设置为on
来使用现有的覆盖率数据。
正如您在报告中看到的,Simulink Design Verifier 将测试生成限制为现有覆盖率文件中未涵盖的覆盖率目标。请注意,Stateflow 图表 control
中的 8 个覆盖率目标被证明是无法满足的。这表明不必要的冗余逻辑无法测试。
cvsave('existingCovFromLoggedSignals',covDataFromLoggedSignals); opts = sldvoptions; opts.IgnoreCovSatisfied = 'on'; opts.CoverageDataFile = 'existingCovFromLoggedSignals.cvt'; opts.ModelCoverageObjectives = 'MCDC'; opts.TestSuiteOptimization = 'LongTestcases'; opts.SaveHarnessModel = 'on'; opts.ModelReferenceHarness = 'on'; opts.MaxProcessTime = 500; [status, fileNames] = sldvrun('slvnvdemo_powerwindow_controller',opts,true); [~, newHarnessModel] = fileparts(fileNames.HarnessModel); open_system(newHarnessModel);
合并来自框架模型的测试用例
现在使用sldvmergeharness
将生成的测试用例与记录的测试用例结合起来。该命令以框架模型列表作为参量。
sldvmergeharness(harnessModel, newHarnessModel);
记录框架模型的测试用例
为了使用合并的框架模型中捕获的测试用例以编程方式执行模型slvnvdemo_powerwindow_controller
,首先使用 sldvlogsignals
函数以必要的数据格式获取所有测试用例的输入值。
loggedSignalsMergedHarness = sldvlogsignals(harnessModel); disp(loggedSignalsMergedHarness);
LoggedTestUnitInfo: [1x1 struct] TestCases: [1x2 struct]
使用 CGV API 在仿真模式下执行模型
使用 sldvruncgvtest
函数在仿真模式下执行模型slvnvdemo_powerwindow_controller
,并从框架模型中捕获测试用例。
runopts = sldvruntestopts('cgv'); disp(runopts); runopts.cgvConn = 'sim'; cgvSim = sldvruncgvtest('slvnvdemo_powerwindow_controller',... loggedSignalsMergedHarness,runopts);
testIdx: [] allowCopyModel: 0 cgvCompType: 'topmodel' cgvConn: 'sim' Starting execution: ComponentType: topmodel Connectivity: sim InputData: /tmp/Bdoc24a_2589924_1833917/tpa0f91cd1/sldv-ex67947267/cgv_runtest/slvnvdemo_powerwindow_controller/slvnvdemo_powerwindow_controller_cgv_input_tc_1.mat End CGV execution: status completed. Starting execution: ComponentType: topmodel Connectivity: sim InputData: /tmp/Bdoc24a_2589924_1833917/tpa0f91cd1/sldv-ex67947267/cgv_runtest/slvnvdemo_powerwindow_controller/slvnvdemo_powerwindow_controller_cgv_input_tc_2.mat End CGV execution: status completed.
使用 CGV API 在软件在环 (SIL) 模式下执行模型
现在使用 sldvruncgvtest
函数以 SIL 模式执行模型slvnvdemo_powerwindow_controller
,使用相同的测试用例。
if canUseSIL runopts.cgvConn = 'sil'; else % When SIL is not possible, the example runs another simulation. runopts.cgvConn = 'sim'; end cgvSil = sldvruncgvtest('slvnvdemo_powerwindow_controller',... loggedSignalsMergedHarness,runopts);
Starting execution: ComponentType: topmodel Connectivity: sil InputData: /tmp/Bdoc24a_2589924_1833917/tpa0f91cd1/sldv-ex67947267/cgv_runtest/slvnvdemo_powerwindow_controller/slvnvdemo_powerwindow_controller_cgv_input_tc_1_1.mat ### Starting build procedure for: slvnvdemo_powerwindow_controller ### Successful completion of build procedure for: slvnvdemo_powerwindow_controller Build Summary Top model targets built: Model Action Rebuild Reason ================================================================================================================== slvnvdemo_powerwindow_controller Code generated and compiled. Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 17.59s ### Preparing to start SIL simulation ... Building with 'gcc'. MEX completed successfully. ### Starting SIL simulation for component: slvnvdemo_powerwindow_controller ### Application stopped ### Stopping SIL simulation for component: slvnvdemo_powerwindow_controller End CGV execution: status completed. Starting execution: ComponentType: topmodel Connectivity: sil InputData: /tmp/Bdoc24a_2589924_1833917/tpa0f91cd1/sldv-ex67947267/cgv_runtest/slvnvdemo_powerwindow_controller/slvnvdemo_powerwindow_controller_cgv_input_tc_2_1.mat ### Starting build procedure for: slvnvdemo_powerwindow_controller ### Successful completion of build procedure for: slvnvdemo_powerwindow_controller Build Summary Top model targets built: Model Action Rebuild Reason ================================================================================================= slvnvdemo_powerwindow_controller Code generated and compiled. Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 11.276s ### Preparing to start SIL simulation ... Building with 'gcc'. MEX completed successfully. ### Starting SIL simulation for component: slvnvdemo_powerwindow_controller ### Application stopped ### Stopping SIL simulation for component: slvnvdemo_powerwindow_controller End CGV execution: status completed.
比较仿真结果和 SIL 模式
sldvruncgvtest
运行测试后返回一个 cgv.CGV
对象。使用 CGV API 比较框架模型中设计的每个测试用例在仿真和 SIL 模式下的执行结果,并显示它们是相等的。
for i=1:length(loggedSignalsMergedHarness.TestCases) simout = cgvSim.getOutputData(i); silout = cgvSil.getOutputData(i); [matchNames, ~, mismatchNames, ~ ] = ... cgv.CGV.compare(simout, silout); fprintf('\nTest Case(%d): %d Signals match, %d Signals mismatch', ... i, length(matchNames), length(mismatchNames)); end
Test Case(1): 4 Signals match, 0 Signals mismatch Test Case(2): 4 Signals match, 0 Signals mismatch
清理
为了完成示例,请关闭所有模型。
close_system(harnessModel,0); close_system(newHarnessModel,0); close_system('slvnvdemo_powerwindow',0); close_system('slvnvdemo_powerwindow_controller',0);