Verify Generated C/C++ Code by Running Existing MATLAB Tests
You can verify the behavior of generated C/C++ code by using MEX
replacement test suites, which are tests that run existing MATLAB® tests and replace the calls to MATLAB functions with calls to MEX functions. MEX replacement test suites use the
matlabtest.coder.MEXReplacementTestSuite
class.
Running MEX replacement test suites uses the matlab.unittest
framework and stores the results in matlab.unittest.TestResult
objects.
MEX replacement test suites have these advantages over verifying generated C/C++ code by
using the coder.runTest
(MATLAB Coder) function:
You can run tests from multiple test files.
You can collect coverage for the generated C/C++ code.
You can generate test and coverage reports from the results.
You can run MEX replacement test suites on continuous integration (CI) platforms.
You can run MEX replacement test suites and MATLAB test suites in the same run by executing a single command.
Note
You can only run MEX replacement test suites programmatically.
Alternatively, you can create and run equivalence tests that generate C/C++ code from MATLAB source code, execute the generated code, and verify that the execution matches the execution of the MATLAB source code. For more information, see Generate C/C++ Code and Test for Equivalence. Use equivalence tests if you need to run tests interactively or need test results that persist across sessions. For more information about running tests, see Run MATLAB Tests.
Generate MEX Function
Before you can create MEX replacement test suites, you must generate a MEX function
from your MATLAB function by using the codegen
(MATLAB Coder) function. For more information, see Generate C Code at the Command Line (MATLAB Coder).
This example code uses the ShortestPath
project to generate a MEX
function from the shortest_path
function with the required input
types and
sizes.
openExample("matlabtest/ShortestPathExample") cfg = coder.config("mex"); mtxType = coder.typeof(ones(100,100),[],1); scalarDbl = coder.typeof(1); codegen shortest_path -args {mtxType,scalarDbl,scalarDbl} -config cfg
Specify Code Generation Configuration for SIL or PIL Verification
With Embedded Coder®, you can verify generated C/C++ code by using software-in-the-loop (SIL) and processor-in-the-loop (PIL) execution. For more information about SIL and PIL execution, see Code Verification Through Software-in-the-Loop and Processor-in-the-Loop Execution (Embedded Coder).
To generate a MEX function for SIL or PIL verification, create a code generation
configuration object for a LIB or DLL build type by using the coder.config
(MATLAB Coder) function. Set the VerificationMode
(MATLAB Coder) property to "SIL"
or
"PIL"
. For PIL verification, configure the Hardware
(MATLAB Coder)
property of your configuration parameter object for your processor hardware by using
the coder.hardware
(MATLAB Coder) function. Use the code generation configuration
object during code generation.
This example code:
Creates a code generation configuration object for a static C library
Sets the verification mode to SIL
Generates code for a function called
foo
that does not take inputs and used the code configuration object
cfg = coder.config("lib"); cfg.VerificationMode = "SIL"; codegen foo -config cfg
Enable Collecting Coverage for Generated Code
To enable collecting coverage for the generated code when you run MEX replacement test suites, use Embedded Coder to generate a static C/C++ library that uses SIL verification:
Create a code generation configuration object for a static library by using the
coder.config
(MATLAB Coder) function.Set the
VerificationMode
(MATLAB Coder) property to"SIL"
.Set the
CodeCoverage
(MATLAB Coder) property totrue
.
Use the code generation configuration object during code generation.
This example code creates a code generation configuration object that enables
collecting coverage for the C code generated from the function
foo
.
cfg = coder.config("lib"); cfg.VerificationMode = "SIL"; cfg.CodeCoverage = true; codegen foo -config cfg
Create Test Suites
To create MEX replacement test suites, use one of the static methods of the matlabtest.coder.MEXReplacementTestSuite
class. Creating the test suite
creates an array of matlab.unittest.Test
objects that use
the same tests that you use to test MATLAB code, but replace the calls to MATLAB functions with calls to MEX functions. You can create test suites that are
based on:
A test file or class
A single test in a file
A folder, namespace, or project that contains tests
Tests that link to requirements
Tip
When you create the test suite, you must specify the MEX function to call. The
default name for the generated MEX function combines the function name with
_mex
, followed by the platform-specific file extension. If
you generate a MEX function for SIL or PIL verification, the MEX function name
combines the function name with _sil
or _pil
,
followed by the platform-specific file extension. To determine the file extension
for the current platform, use the mexext
function.
This example code uses the ShortestPath
project to create a MEX
replacement test suite based on tests from the graph_unit_tests.m
test file and specifies the MEX file to call as
shortest_path_mex.mexw64
.
import matlabtest.coder.MEXReplacementTestSuite testFile = "tests/graph_unit_tests.m"; mexFcn = which("shortest_path_mex.mexw64"); suite = MEXReplacementTestSuite.fromFile(testFile,mexFcn);
Run Test Suites
To run MEX replacement test suites, use the run
method of matlab.unittest.TestSuite
. You can
only run MEX replacement test suites programmatically.
This example code runs a test suite stored in a variable called
suite
and stores the results in a
variable.
results = run(suite);
Setting up MEXReplacementFixture Done setting up MEXReplacementFixture: Replacing MATLAB function calls with the specified MEX functions __________ Running graph_unit_tests .......... .... Done graph_unit_tests __________
Collect Coverage
To collect coverage for the generated C/C++ code when you run MEX replacement test suites:
Define the coverage format by creating an instance of
matlab.unittest.plugins.codecoverage.CoverageResult
.Create a plugin for the generated C/C++ code by creating an instance of
matlabtest.coder.plugins.GeneratedCodeCoveragePlugin
. Specify the desired coverage type for the plugin or use the default settings, which specify statement and function coverage.Create a test runner by using the
testrunner
function.Add the code coverage plugin to the test runner by using the
addPlugin
method.Run the test suite by using the
run
method ofmatlab.unittest.TestRunner
. Store the test results in a variable.
This example code configures the test runner to collect coverage for
the generated C code, runs the MEX replacement test suite that is stored in a
variable called suite
, and stores the test results in a
variable.
import matlab.unittest.plugins.codecoverage.CoverageResult import matlabtest.coder.plugins.GeneratedCodeCoveragePlugin format = CoverageResult; plugin = GeneratedCodeCoveragePlugin(Producing=format, ... MetricLevel="mcdc"); runner = testrunner("textoutput"); addPlugin(runner,plugin); results = run(runner,suite);
Setting up MEXReplacementFixture Done setting up MEXReplacementFixture: Replacing MATLAB function calls with the specified MEX functions __________ Running graph_unit_tests ### Starting SIL execution for 'shortest_path' To terminate execution: clear shortest_path_sil .......... .... Done graph_unit_tests __________ Tearing down MEXReplacementFixture ### Application stopped ### Stopping SIL execution for 'shortest_path' Code coverage report: getCodeCoverageData('shortest_path_sil') Done tearing down MEXReplacementFixture __________
View and Report Test Results
To view the test results programmatically, access the variable that contains the test
results in the MATLAB Command Window. To generate a test report from the test results, use the
generateHTMLReport
method of the matlab.unittest.TestResult
class.
This example code displays the test results stored in a variable called
results
, then generates an HTML test report called
shortest_path_mex_results
and saves it in the
reports
folder.
results
results = 1×14 TestResult array with properties: Name Passed Failed Incomplete Duration Details Totals: 14 Passed, 0 Failed, 0 Incomplete. 1.4171 seconds testing time.
reportPath = fullfile("reports","shortest_path_mex_results.html"); generateHTMLReport(results,reportPath);
Adding content to the test report. Writing test report to file. Test report has been saved to: C:\Users\jdoe\MATLAB\reports\shortest_path_mex_results.html
View and Report Coverage Results
The Result
property of the matlab.unittest.plugins.codecoverage.CoverageResult
object contains the
coverage results. To view the coverage results programmatically, use the coverageSummary
method. To generate an HTML coverage report, use the
generateHTMLReport
method. For more information about the code
coverage report, see Collect Code Coverage Metrics for MATLAB Source Code.
Alternatively, to generate a standalone report as a single HTML file, use the
generateStandaloneReport
method.
This example code stores the coverage results in a variable, generates an HTML
report from the results called shortest_path_mex_cov_results
and
stores it in the reports
folder, then accesses the statement
coverage results
programmatically.
covResults = format.Result; cReportPath = fullfile("reports","shortest_path_mex_cov_results.html"); generateHTMLReport(covResults,cReportPath); covSummary = coverageSummary(covResults,"statement")
covSummary = 9×2 39 44 18 21 0 2 0 4 1 4 70 79 2 2 0 47 2 2