主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

评估模型与代码覆盖率之间的差异

此示例演示了如何使用 Simulink® Test™ Manager 分析模型覆盖率和生成代码覆盖率,并调查结果中的差异。有关如何在不使用 Simulink Test 的情况下分析代码覆盖率的信息,请参阅使用 Simulink Coverage 收集代码覆盖率度量软件在环代码覆盖率

在分析代码覆盖率时,代码覆盖率结果可能与模型覆盖率结果不完全一致。

尽管 Embedded Coder 的目标是生成与模型行为相同的代码,但 Simulink® 模型和 C/C++ 代码在抽象层次上存在根本差异。Simulink 模型是期望行为的高级表示,而 C 和 C++ 是低级编程语言。由于这种差异,行为的实现方式不同,可能导致结构不同。

模型和代码覆盖率结果可能存在差异,原因可能包括:

  • 语句覆盖率与模块执行覆盖率不同。例如,Stateflow® 图和转移不会获得模块执行覆盖率,但从它们生成的代码会获得语句覆盖率。此外,由于一个模块的实现通常包含多个代码语句,因此一个模块的执行结果通常会对应生成代码中的多个语句.

  • 模型覆盖率中的“整数溢出饱和”度量在代码覆盖率中成为决策结果。

  • 在 MATLAB® Function 模块内部的函数调用,在模型覆盖率中会报告为一个决策,但在代码覆盖率中会报告为函数调用覆盖率。

  • Embedded Coder 会尝试优化生成的代码,以消除不必要的执行分支。如果你的模型中存在死逻辑,Embedded Coder 可能会从生成代码中移除这些逻辑。

  • 默认情况下,Embedded Coder 会执行表达式折叠优化,即将多个决策折叠为一个更复杂的决策。此优化可能会导致决策、条件和多条件死代码覆盖率 (MCDC) 的差异。有关详细信息,请参阅Minimize Computations and Storage for Intermediate Results at Block Outputs (Embedded Coder)

设置覆盖率

此示例模型 CruseControl.slx 是一个实现简单巡航控制逻辑的 Stateflow 图。

此示例包含一个 Simulink® Test™ 测试文件,该文件包含一组测试用例,可实现 100% 模型覆盖率,随后利用这些测试用例通过软件在环 (SIL) 仿真模式分析代码覆盖率。

打开 Simulink 测试管理器并加载测试用例。

sltestmgr
testFile = sltest.testmanager.load("CruiseControl_Tests.mldatx");

运行测试套件

使用 sltest.testmanager.run 运行测试套件。不提供任何输入将运行所有已加载的测试。

testFile.run();

在测试管理器中查看覆盖率结果

在测试管理器中,点击结果和工件。展开结果,然后选择 CruiseControl_Tests > CruiseControl_TestSuite > Model-in-the-loop Tests。然后,在聚合覆盖率结果下,通过点击创建聚合覆盖报告图标 open-report-icon.png 来生成模型覆盖率报告。在这组测试中,模型覆盖率报告器显示决策覆盖率、条件覆盖率和 MCDC 覆盖率均为 100%。

在左侧窗格中,选择 CruiseControl_Tests > CruiseControl_TestSuite > Software-in-the-loop Tests。在聚合覆盖率结果下,通过点击创建聚合覆盖报告图标 open-report-icon.png 生成代码覆盖率报告。这些测试使用相同的测试用例和测试输入,但代码覆盖率报告显示决策覆盖率为 97%,条件覆盖率为 96%,MCDC 覆盖率为 91%。要理解造成这种差异的原因,需要进一步分析覆盖率报告。

审查代码覆盖率报告

在启用了覆盖率结果突出显示的情况下查看模型。在测试管理器中,进入 Software-in-the-loop Tests 结果,在聚合覆盖率结果下,点击要分析的模型名称 CruiseControl,打开模型的覆盖率详细信息窗格,并突出显示具有覆盖率结果的模型。双击以进入 Compute target speed 图。

Stateflow chart highlighted with green and red to indicate coverage completeness. The source of most of the red in the chart is two transitions that exit the Standby chart.

覆盖率详细信息窗格中,滚动至详细信息部分。详细信息部分的第一部分显示了整个系统的覆盖率结果。在模型覆盖率报告中,所针对的模型为 CruiseControl,而在代码覆盖率报告中(即当前覆盖率详细信息窗格显示的报告),所针对的文件为 CruiseControl.c。模型覆盖率和代码覆盖率报告分别显示如下覆盖率结果:

覆盖率度量

模型覆盖率结果

代码覆盖率结果

决策

100%(38 个结果,总共 38 个)

97%(38 个结果,总共 39 个)

条件

100%(32 个结果,总共 32 个)

96%(69 个结果,总共 72 个)

MCDC

100%(16 个结果,总共 16 个)

91%(20 个结果,总共 22 个)

执行

不适用

不适用

语句

不适用

100%(89 个语句,总共 89 个)

函数

不适用

100%(5 个函数,总共 5 个)

函数调用

不适用

100%(3 个函数调用,总共 3 个)

通过比较结果,您可以发现决策、条件和 MCDC 覆盖率在代码覆盖率报告器中具有更多的覆盖率结果。

审查具体差异

在 Simulink 画布中,有两个转移未被覆盖。点击下方的转移,[hasChangedTo(CoastSetSw,true)]。在模型覆盖率报告中,您会看到一个经过分析的决策,该决策有两个可能的结果,这就是决定是否进行此次转移的最终决策。然而,在代码覆盖率报告中,您会看到一个经过分析的决策,该决策有两个可能的结果;两个经过分析的条件,每个条件都有两个可能的结果;以及两个 MCDC 结果。

Code coverage report for the Stateflow transition

当模型以代码覆盖率结果高亮显示时,点击转移线可跳转至代码覆盖率报告中的相应代码部分。如果您向上滚动至详细信息部分,即可查看覆盖率表格。在本例中,第 3.18 节是与本次转移相关的部分。

codecov-sf-transition-details.png

分析的条件MC/DC 分析表格说明了代码覆盖率报告中出现新结果的原因。hasChangedTo 运算符在模型覆盖率中会报告为一个决策,而 Embedded Coder® 则会将该转移转换为一个包含多个条件的复杂表达式,因此它还接收条件覆盖率和 MCDC 覆盖率:

else if ((CruiseControl_DW.CoastSetSw_prev != CruiseControl_DW.CoastSetSw_start) && CruiseControl_DW.CoastSetSw_start) {...}

解决代码覆盖率缺失问题

在此示例中,代码覆盖率分析未达到 100% 覆盖率,因为生成的代码产生了额外需要满足的覆盖率结果。要实现 100% 覆盖率,您可以:

  • 添加新的测试用例,以覆盖当前测试用例未涉及的逻辑。您可以使用 Simulink® Design Verifier™ 生成测试用例以满足缺失的覆盖率。

  • 如果一个或多个测试结果无法达到预期,或者测试用例需要过多的系统资源,请对覆盖率结果进行申述。

作为最佳作法,建议在分析代码覆盖率之前,先解决模型覆盖率缺失的问题。例如,如果模型覆盖率报告中存在决策覆盖缺失,则生成代码的代码覆盖率报告中也会存在相应的语句覆盖缺失。此外,您可以重用用于分析模型覆盖率的测试用例进行代码覆盖率分析,从而验证它们的行为等价性。

另请参阅

(Simulink Coder)

主题