Main Content

Test Library Blocks

If your model includes instances of blocks from a library, you can test both the source block in the library, and individual block instances in other models. You can also test software-in-the-loop (SIL) code generated for a reusable library subsystem. First, create test harnesses for a library block to test your design. Once the library block meets your requirements, create test harnesses for linked blocks and test the subsystem instances.

Library Testing Workflow

This procedure outlines an example workflow for testing library subsystems and linked subsystems.

  1. Create a test case and a test harness for the library subsystem.

  2. Test the library subsystem. If it fails your requirements, revise the design and test again.

  3. Lock the library when your tests pass.

  4. In your model, create a linked subsystem and retain the library test harnesses.

  5. Compare the output of the linked instance to that of the library block using an equivalence test case.

  6. Create additional test cases and test harnesses for the linked instance.

  7. Promote a test harness from the linked subsystem to the library if you want to include the test harness with future linked subsystems.

Library and Linked Subsystem Test Harnesses

A test harness for a library subsystem has specific properties:

  • Libraries do not compile, so a test harness for a library subsystem does not use compiled attributes such as data type or sample rate.

  • A test harness for a library subsystem does not generate conversion subsystems for the block inputs and outputs.

  • A library subsystem test harness does not use push or rebuild operations, because libraries do not use configuration parameters.

When you create a linked subsystem from a library subsystem, test harnesses copy to the linked instance. If you do not need the test harnesses, you can delete them. For instructions on deleting all test harnesses from a model, see Manage Test Harnesses.

When you create a test harness for a linked subsystem, the harness associates with the linked subsystem, not the library subsystem. You can move a test harness from a linked subsystem to the library subsystem. For example, this linked subsystem Controller has three test harnesses. To move the Requirements_Tests1 test harness to the library:

  1. Click the harness badge on the linked subsystem.

  2. Click the Harness Operations icon.

    Controller harnesses badges

  3. Select Move to Library.

  4. A dialog box informs you that moving the harness removes it from the linked subsystem.

  5. After confirmation, the harness appears with the library subsystem.

Edit Library Block from a Test Harness

You can apply an iterative design and test workflow to libraries by testing a library block in a test harness and updating the component under test. Changes to the component under test synchronize to the library when you close the test harness.

If you have a library block whose design is complete, set your test harnesses to prevent changes to the component under test. You can set this property when you create the test harness or after harness creation. See Create or Import Test Harnesses and Select Properties.

Testing a Library and a Linked Block

Verify a reusable subsystem in a library and in a larger system.

This example demonstrates a test case that confirms a library block meets a short set of requirements. After testing the library block, you execute a baseline test of a linked block and capture the baseline results. You then promote the baseline test harness to the library.

The library block controls a simple heat pump system by supplying on/off signals to a fan and compressor, and specifying the heat pump mode (heating or cooling).

Open the Test File

Enter the following to store paths and filenames for the example, and to open the test file. The test file contains a test case for the library block and for the block instance in a closed-loop model.

testFile = 'sltestHeatpumpLibraryTests.mldatx';
library = 'sltestHeatpumpLibraryExample';
system = 'sltestHeatpumpLibraryLinkExample';
sltest.testmanager.load(testFile);
sltest.testmanager.view;

Expand the Library Block Test test suite, and highlight the Requirements Scenarios test case in the test browser. Expand the Test Harness section of System Under Test, and click the arrow to open the test harness for the library block.

open_system(library);
sltest.harness.open([library '/Controller'],'Requirements_Tests');

The Test Sequence block sets three scenarios for the controller:

  • The controller at idle

  • The controller activating the fan only

  • The controller activating the heating and cooling system

The Test Assessment block in the test harness checks the signals for each scenario. Since the test inputs and assessments are contained in the test harness, and no baseline data is being captured, the test case is a simulation test.

Run the Requirements-Based Test

In the test manager, run the Requirements Scenarios test case. The verify statement results show that the control_out signals pass.

Open the Linked Block Model

In the test manager, expand Instance Test. Highlight the Baseline Test test case. In the System Under Test, click the arrow next to the Model field to open the model.

sltest.harness.close([library '/Controller'], 'Requirements_Tests');
open_system(system);
sim(system);

The controller is a linked block to the library. It is associated with a test harness Baseline Test that compares simulation results of the instance against baseline data. In your workflow, successful baseline testing for an instances of a library block can show that the linked block simulates correctly in the containing model. The test harness supplies a sine wave temperature and captures the controller output.

Run the Baseline Test and Observe Results

In the test manager, click Run to execute the test. The results show that the baseline test passes.

Move the Test Harness to the Library

If you develop a particularly useful test for a linked block, you can promote the test harness from a linked block to the source library block. The test harness then copies to all future instances of the library block.

Move the Baseline_controller_tests test harness to the library block:

1. In the sltestHeatpumpLibraryLinkExample model, click the harness badge and hover over the Baseline_controller_tests test harness.

2. Click the harness operations icon

3. Select Move to Library. A dialog informs you that the operation deletes the test harness from the instance and adds it to the library. Click Yes.

4. The test harness moves to the Controller library block.

close_system(library,0);
close_system(system,0);
clear(library,system,testFile);
sltest.testmanager.clear;
sltest.testmanager.clearResults;

SIL Testing a Reusable Library Subsystem

This example shows how to unit test a reusable component in a library. It tests software-in-the-loop (SIL) code generated for a subsystem by using an equivalence test.

The reusable library subsystem must be at the top level of the library and must have function interfaces to lock down the subsystem interface. For information on reusable subsystem libraries, function interfaces, and workflow limitations, see Library-Based Code Generation for Reusable Library Subsystems (Embedded Coder).

Set Up the Code Generation Environment

orig = Simulink.fileGenControl('get','CodeGenFolderStructure');
Simulink.fileGenControl('set','CodeGenFolderStructure',...
    Simulink.filegen.CodeGenFolderStructure.TargetEnvironmentSubfolder);

Open the Reusable Library

This library contains a subsystem block at the top level.

ReuseLibSubsysExample

Build the Library

Build the reusable library to generate code and create the function interfaces. After the code generation completes, you can view the function interfaces by clicking the lower right corner the library to open the Manage Function Interfaces dialog box.

slbuild('ReuseLibSubsysExample');
### Unable to find Simulink cache file "ReuseLibSubsysExample.slxc".
### Searching for referenced models in model 'Double'.
### Total of 1 models to build.
### Starting build procedure for: Double
### Generating code and artifacts to 'Target environment subfolder' folder structure
### Generating code into build folder: /tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/Double
### Invoking Target Language Compiler on Double.rtw
### Using System Target File: /mathworks/devel/bat/filer/batfs2566-0/Bdoc25a.2864802/build/runnable/matlab/rtw/c/ert/ert.tlc
### Loading TLC function libraries
.......
### Initial pass through model to cache user defined code
.
### Caching model source code
...............................................
### Writing source file Subsystem_gmjUKRe0.c
### Writing header file Double_types.h
.
### Writing header file Double.h
### Writing header file rtwtypes.h
### Writing header file Subsystem_gmjUKRe0.h
### Writing source file Double.c
### Writing header file Double_private.h
.
### Writing source file ert_main.c
### TLC code generation complete (took 2.582s).
### Saving binary information cache.
### Using toolchain: GNU gcc/g++ | gmake (64-bit Linux)
### Creating '/tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/_shared/rtwshared.mk' ...
### Using toolchain: GNU gcc/g++ | gmake (64-bit Linux)
### Creating '/tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/Double/Double.mk' ...
### Successful completion of code generation for: Double

The following files will be copied from IntelWin64/_shared to /tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/ReuseLibSubsysExample/R2025a:

    Subsystem_gmjUKRe0.c
    Subsystem_gmjUKRe0.h
    shared_file.dmr

Files copied from IntelWin64/_shared to /tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/ReuseLibSubsysExample/R2025a.
### Searching for referenced models in model 'Single'.
### Total of 1 models to build.
### Starting build procedure for: Single
### Generating code and artifacts to 'Target environment subfolder' folder structure
### Generating code into build folder: /tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/Single
### Invoking Target Language Compiler on Single.rtw
### Using System Target File: /mathworks/devel/bat/filer/batfs2566-0/Bdoc25a.2864802/build/runnable/matlab/rtw/c/ert/ert.tlc
### Loading TLC function libraries
.......
### Initial pass through model to cache user defined code
.
### Caching model source code
...............................................
### Writing source file Subsystem_TZgYvBnF.c
### Writing header file Single_types.h
.
### Writing header file Single.h
### Writing header file Subsystem_TZgYvBnF.h
### Writing source file Single.c
### Writing header file Single_private.h
### Writing source file ert_main.c
.
### TLC code generation complete (took 1.298s).
### Saving binary information cache.
### Using toolchain: GNU gcc/g++ | gmake (64-bit Linux)
### Creating '/tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/_shared/rtwshared.mk' ...
### Using toolchain: GNU gcc/g++ | gmake (64-bit Linux)
### Creating '/tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/Single/Single.mk' ...
### Successful completion of code generation for: Single

The following files will be copied from IntelWin64/_shared to /tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/ReuseLibSubsysExample/R2025a:

    Subsystem_TZgYvBnF.c
    Subsystem_TZgYvBnF.h
    shared_file.dmr

Files copied from IntelWin64/_shared to /tmp/Bdoc25a_2864802_2048071/tp8331ebc6/simulinktest-ex98874249/IntelWin64/ReuseLibSubsysExample/R2025a.

Open the Test Manager

Click the Subsystem in the library model to select it. Then, open the Test Manager.

sltest.testmanager.view

Open the Test File

  1. In the Test Manager, click Open and select the ReuseLibSubsysTest.mldatx file.

Enable Coverage Collection

  1. Select ReuseLibSubsysTest in the Test Browser pane.

  2. Then, expand the Coverage Settings section in the main pane.

  3. In Coverage to Collect, check Record coverage for system under test and Record coverage for referenced models.

  4. In Coverage Metrics, check that Decision, MCDC, and Condition are selected.

Open the Create Test for Model Component wizard

  1. Click New > Test for Model Component to open the Create Test for Model Component wizard.

  2. On the System page of the wizard, click the second icon (Use current model) next to the Top Model field. Both the Top Model field and components hierarchy fill in.

  3. Select Subsystem in the components hierarchy and click the plus sign. The Subsystem component is added to the Selected components.

  4. Click the refresh icon next to Select function interface and select Double from the dropdown.

  5. Click Next.

Select the Test Inputs

  1. On the Test Inputs page, select Use Design Verifier to generate test input scenarios. Then click Next.

Select How to Test the Component

  1. On the Verification Strategy page, select Perform back-to-back testing.

  2. Set Simulation1 to Normal mode.

  3. Set Simulation2 to Software-in-the-Loop (SIL) mode.

  4. Click Next.

Specify the Input Source, Data File Format, and Test File

  1. On the Generated Test page, select Inports as the test harness input source.

  2. Select MAT as the file format.

  3. Select Add tests to currently selected test file.

Generate the Test Case and Return to the Test Manager

Click Done to generate the Double_Harness1 test case for the Double function interface.

After test case generation completes, the Double_Harness1 test case appears in the Test Browser pane of the Test Manager. To check that the Simulation Modes are set correctly, expand Simulation 1 > System Under Test > Simulation Settings and Release Overrides. Expand Simulation 2 in the same way. The Simulation Mode for Simulation 1 is set to Normal and Simulation 2 is set to Software-in-the-Loop (SIL).

Run the Test

Click Run in the Test Manager toolstrip.

View Equivalence Results

  1. Expand the Results > Double_Harness1 > Iteration2.

  2. Select Equivalence Criteria Result.

  3. In the Compare pane, select the Out1:1 signal if it is not already selected.

Notice that the Difference plot shows no differences between the two signals, which indicates that the Normal and SIL simulations produce the same results. You can reuse the SIL code associated with the reusable library subsystem for other SIL tests.

View Coverage Results

Select Results( in the *Results and Artifacts pane. The Aggregated Coverage Results section shows the combined model coverage. The two coverage results that show 100% are for the equivalence test run for the Double function interface. The other result shows 0% because the Single function interface was not tested.

Clean up

Simulink.fileGenControl('set','CodeGenFolderStructure',orig);

See Also

Topics