Main Content

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

使用向导对导入的自定义代码进行单元测试

此示例显示如何使用代码导入器向导将热泵控制器的自定义 C 代码导入 Simulink 进行单元测试。单元测试独立于自定义代码库测试一个或多个函数。对于单元测试,Simulink Test 代码导入器向导会生成一个测试沙箱和一个库,其中包含来自自定义代码的每个指定函数的 C Caller 模块。更多信息请参阅导入和测试自定义 C/C++ 代码

此示例仅使用 tempController.c 文件创建并导入测试沙箱到 Simulink。您使用沙箱仅对 tempController.c 文件中的 heatpumpController 函数执行单元测试,而不是对完整代码执行单元测试。生成沙盒会自动为 heatpumpController 函数、absoluteTempDifferencepumpDirection 使用的实用函数创建桩件。由于实用函数未在 tempController.c 文件中定义,并且未包含 utils.cutils.h 文件,因此代码导入器会创建桩件,因此代码不会出错。

热泵控制器自定义代码

热泵控制器的完整代码位于以下 C 代码源和头文件中:

源文件位于 src 目录中:

  • tempController.c

  • utils.c

头文件位于 include 目录中:

  • tempController.h

  • utils.h

  • controllerTypes.h

tempController.c 文件包含热泵机组的自定义 C 代码的算法。该文件中的 heatpumpController 函数使用室温 (Troom_in) 和设定温度 (Tset) 作为输入。输出是 pump_control_bus 类型结构体,其信号控制风扇、热泵以及热泵的方向(加热或冷却)。pump_control_bus 结构体中的字段是 fan_cmdpump_cmdpump_dirpump_control_bus 结构体类型在 controllerTypes.h 文件中定义。heatpumpController 函数的输出是:

heatpumpController 算法的输出总结如下表:

TemperatureSystemFanPumpPumpConditionStateCommandCommandDirection|Troom_in - Tset| < DeltaT_fanIdle00IDLEDelatT_fan <= |Troom_in - Tset| < DeltaT_pumpFan only10IDLE|Troom_in - Tset| >= DeltaT_pump and Tset < Troom_inCooling11COOLING|Troom_in - Tset| >= DeltaT_pump and Tset > Troom_inHeating11HEATING

heatpumpController 函数使用了两个实用函数 absoluteTempDifference pumpDirection,它们在 utils.c 文件中定义。absoluteTempDifference 函数以双精度形式返回 Tset Troom_in 之间的绝对差。pumpDirection 函数返回以下 PumpDirection 类型枚举值之一:

Temperature ConditionPump DirectionTset < Troom_inCOOLINGTset > Troom_inHEATING

PumpDirection 枚举 typecontrollerTypes.h 文件中定义。

打开代码导入向导

要打开 Simulink Test C/C++ 代码导入器向导,首先打开 Simulink Test 管理器。

sltest.testmanager.view

然后,选择新建 > 测试 C/C++ 代码

指定 Simulink 库和测试方法

向导打开并显示欢迎选项卡。单击开始即可开始导入过程。

Code importer wizard welcome tab that summarizes the wizard capabilities

设置选项卡上:

  1. 输入 Simulink 库文件名。生成的 Simulink 库、测试沙盒目录和测试文件(MLDATX)使用此名称。输入 heatpumpController

  2. 指定用于保存所生成工件的输出文件夹。输入可写文件夹的名称。

  3. 选择 C 代码单元测试作为测试方法。

C 代码单元测试方法单独测试一个 C 文件或自定义代码的子集。此方法从指定的源文件或文件创建测试沙盒,并将测试沙盒导入 Simulink。由于测试沙箱仅包含 C 文件的子集,因此代码导入器向导会自动为 C 文件中使用的所有未定义符号创建桩件。此方法仅支持测试 C 代码。有关集成测试的信息,请参阅 sltest.CodeImporterTestType 属性。

Code import wizard output library file name and output folder, plus testing method

点击下一步

指定要导入的自定义代码

指定自定义代码选项卡上:

  1. 源文件中,指定包含要导入进行单元测试的函数的源文件。输入 .\src\tempController.c

  2. 包含目录中,指定指定的源文件所依赖的目录。输入 .\include

  3. Defines 指定特定于编译器的定义。对于此示例,将此字段留空。

Custom code importer wizard tab for specifying source files, include directories, and defines

点击下一步

指定测试沙盒设置

分析选项卡上,指定沙盒设置。

选择输出测试沙盒模式

三种测试沙盒模式中的每一种都有设置来决定代码导入器向导如何生成沙盒和沙盒工件。

选择生成聚合标头。该测试沙盒模式为指定的源文件生成最小的聚合头文件。聚合头文件包含指定源文件所使用的符号的所有声明。

选择输出测试沙盒设置

仅选择复制源文件。对于此选项,代码导入器向导将指定的源文件复制到沙箱 src 目录。

有关其他输出测试沙盒模式和设置的信息,请参阅 sltest.CodeImporter.SandboxSettings 的属性。

Custom code importer wizard tab for sandbox output mode and settings

单击下一步以使用指定的设置创建测试沙盒。

创建测试沙盒

指定的库文件名决定了生成的沙箱的名称。对于此示例,沙盒名称是 heatpumpController_sandbox

此示例使用 tempController.c 并仅对 heatpumpController 函数执行单元测试。生成沙盒会自动为 heatpumpController 函数使用的 absoluteTempDifferencepumpDirection 实用函数创建桩件,由于实用函数未在 tempController.c 文件中定义,因此桩件会阻止代码出错。

创建沙箱后,将显示确认屏幕。

Custom code importer wizard tab to update sandbox

输出沙盒文件夹包含以下子文件夹:

  • src:此文件夹包含复制的源文件,本例中为 tempController.c

  • include:根据测试沙盒模式,该文件夹包含 aggregatedHeader.hinterfaceHeader.h 文件。此示例使用 aggregatedHeader.h 文件。该文件夹还包含编译指定的源文件所需的其他头文件的副本。aggregatedHeader.h 文件包含指定源文件所使用的所有符号的声明。interfaceHeader.h 包含指定源文件使用的函数、全局变量和类型的声明。Simulink 在导入过程中使用生成的接口头文件。

  • autostub:此文件夹包含 auto_stub.cauto_stub.h 文件,其中保存了 absoluteTempDifference pumpDirection 实用函数 . 的自动生成的桩件

  • manualstub:此文件夹包含 man_stub.cman_stub.h 文件,它们定义任何手动指定的桩件。默认情况下,这些文件没有定义任何函数。

注意:请勿修改生成的沙盒的 srcincludeautosub 文件夹中的文件。

沙盒创建完成后,可以查看创建的文件:

  • 单击 Auto stub sourceAuto stub header 分别打开 auto_stub.c 和 auto_stub.h 文件。在 auto_stub.c 中,您可以找到 heatpumpControllerabsoluteTempDifferencepumpDirection 使用的实用函数的桩件。在 auto_stub.h 中,您可以找到桩件函数的 extern 声明。

  • 单击手动桩件标头手动桩件源分别打开 man_stub.hman_stub.c 文件。由于您为沙盒模式选择了生成聚合标头,因此沙盒中 man_stub.h 包含了 aggregatedHeader.h 文件。默认情况下,手动桩件文件没有任何函数定义。

点击下一步

指定导入设置

指定使用全局变量作为函数接口

当向导检测到沙箱或自定义代码中的全局变量时,您可以选择使用这些变量作为创建的 C Caller 模块上的函数和端口的输入或输出。有关更多信息,请参阅 Enable global variables as function interfaces

选择启用全局变量作为函数接口选项。

Custom code importer wizard tab to enable global variables

点击下一步

选择要导入的函数

导入页面,选择 heatpumpController 函数导入到 Simulink 库中。

Custom code importer wizard tab to select functions to import

点击下一步

设置模块端口规格

对于您在上一页中选择的功能,向导将生成功能端口规范。选定的端口用于生成的 C Caller 模块。请注意,如果要导入的代码具有带指针输出的函数,则需要在向导的此页面上指定输出端口的大小。

Custom code importer wizard tab to edit block port specifications

在此示例中,端口规范表列出了 heatpumpController 函数的正式参量 TsetTroom_inout,以及来自自动生成的桩件的另外六个参数。由于您选择了启用全局变量作为函数接口,因此向导会创建从 absoluteTempDifferencepumpDirection 函数的桩件生成的端口。桩件在 auto_stub.c 中。

这些是 auto_stub.c 文件中自动生成的全局变量:

/*************************************************************************/
/* Generated Global Variables for Stubbed Functions Interface            */
/*************************************************************************/
double SLStubIn_absoluteTempDifference_p1;
double SLStubIn_absoluteTempDifference_p2;
double SLStubOut_absoluteTempDifference;
double SLStubIn_pumpDirection_p1;
double SLStubIn_pumpDirection_p2;
PumpDirection SLStubOut_pumpDirection;

double absoluteTempDifference(double absoluteTempDifference_p1, double absoluteTempDifference_p2)
{
  SLStubIn_absoluteTempDifference_p1 = absoluteTempDifference_p1;
  SLStubIn_absoluteTempDifference_p2 = absoluteTempDifference_p2;
  return SLStubOut_absoluteTempDifference;
}


PumpDirection pumpDirection(double pumpDirection_p1, double pumpDirection_p2)
{
  SLStubIn_pumpDirection_p1 = pumpDirection_p1;
  SLStubIn_pumpDirection_p2 = pumpDirection_p2;
  return SLStubOut_pumpDirection;
}

在自动生成的 absoluteTempDifference 的桩件中,全局变量 SLStubIn_absoluteTempDifference_p1SLStubIn_absoluteTempDifference_p2 保存了输入参量。该函数返回存储在 SLStubOut_absoluteTempDifference 中的值作为其输出。类似地,pumpDirection 保存输入参量并返回 SLStubOut_pumpDirection

在此示例中,absoluteTempDifferenceSLStubIn_absoluteTempDifference_p1SLStubIn_absoluteTempDifference_p2 是输出。全局变量 SLStubOut_absoluteTempDifference 是一个输入。

不要对端口规范做任何更改。点击下一步

指定要导入的类型

选择要导入到 Simulink 的类型。因为 pump_control_bus PumpDirection 类型是 heatpumpController 函数所需要的,所以它们被选中并变暗。向导创建一个包含这些类型的 Simulink 数据字典,并将该字典链接到生成的库。

Custom code importer wizard tab to select import types

单击下一步显示生成的库的摘要。再次单击下一步继续。

创建测试框架

选择自动为所有导入的功能创建测试框架

Custom code importer wizard tab to select whether to create a test harness

点击下一步生成 Simulink 库。

代码导入后,向导会创建一个附加到 Simulink 数据字典的库,该库分别将 pump_control_busPumpDirection 定义为 Simulink.Bus 对象和 Simulink 枚举信号。

在 Simulink 库中创建的 C Caller 模块是:

Heat pump controller showing inputs and outputs

单击模块的右下角以打开其内部测试框架:

Heat pump controller test harness

在代码导入成功页面上,点击将 MATLAB 文件夹更改为输出文件夹

请不要点击完成。继续下一部分,手动更新未定义符号的桩件。

Custom code importer wizard tab showing that code import was successful

使用手动插桩更新测试沙箱

要手动创建 absoluteTempDifferencepumpDirection 的桩件文件,点击向导工具栏中的分析选项卡,然后点击下一步两次以显示此页面:

Custom code importer wizard tab to update the stub files or overwrite the existing sandbox

代码导入器检测您创建的沙箱。选择覆盖,然后点击下一步

在向导之外,但保持向导打开,复制 updated_manualstub 目录中的文件并将其粘贴到沙箱 .manualstub 目录中

man_stub.c 文件中,编辑 absoluteTempDifference 的函数定义:

double absoluteTempDifference(double Tset, double Troom_in){ 
    return (double)fabs(Tset - Troom_in);
}

以及 pumpDirection 的函数定义:

PumpDirection pumpDirection(double Tset, double Troom_in){
    return Tset > Troom_in ? HEATING : COOLING;
}

返回代码导入器向导。

Custom code importer wizard tab showing that sandbox has been created

修改手动桩件文件后,返回向导并点击更新沙盒

因为您手动定义了 absoluteTempDifferencepumpDirection 函数的定义,所以没有符号可以自动桩件,沙箱中的 autostub 目录没有生成工件,并且它是空的。

Custom code importer wizard tab showing Update Sandbox button

单击下一步,直到到达模块端口规范页面:

Custom code importer wizard tab to edit block port specifications for selected functions

因为 absoluteTempDifferencepumpDirection 的手动实现没有任何全局变量,所以只有形式参量和返回参量作为端口出现。

点击下一步

创建 Simulink 库选项卡上,选择覆盖

Custom code importer wizard tab to

单击下一步,浏览剩余页面,直到到达代码导入成功页面。

然后点击完成。如果需要,请在打开的对话框中点击,将当前导入设置保存为 JSON 文件,然后使用该文件将设置重新加载到另一个代码导入器向导会话中。

测试导入的代码

在测试管理器的测试浏览器窗格中展开 heatpumpController 测试文件和 heatpumpController/heatpumpController 测试套件。然后选择 heatpumpController_Harness1 测试用例。

指定仿真停止时间

在测系统部分中,展开仿真设置和发布覆盖部分,并将停止时间设置为 200。

Simulink Test Manager with stop time set to 200

添加输入

输入部分中,在外部输入表的底部,点击添加以打开添加输入对话框。

输入文件规范中,输入 heatpumpControllerHarnessInput.xlsx

输入映射下,选择 Block Name 作为映射模式,然后点击映射输入。输入出现在映射状态表中后,点击确定

Simulink Test manager

添加评估

逻辑和时序评估部分,添加针对每种温度条件的评估:

Simulink Test Manager assessments details

有关评估的信息,请参阅 使用时序评估来评估时序逻辑

在符号窗格中,添加符号定义:

Assessments symbols details

Additional assessments symbols

运行测试并查看结果

单击运行来运行测试。

测试完成后,在结果和工件窗格中,展开结果。全部评估均通过。

Test results showing assessment number 1 passing result

要查看覆盖率结果,请选择结果下的 heatpumpController_Harness1,并展开覆盖率结果部分。tempController.cman_stub.c 文件的覆盖率均为 100%。

Coverage results showing 100% coverage

相关主题