MATLAB Examples

Unit Test Generated Code with MATLAB Coder

This example shows how to test the output of generated code by using MATLAB® unit tests with MATLAB® Coder™.

To monitor for regressions in code functionality, you can write unit tests for your code. In MATLAB, you can create and run unit tests by using the MATLAB testing framework. To test MEX code and standalone code that you generate from MATLAB code, you can use the same unit tests that you use to test MATLAB code.

A MEX function includes instrumentation that helps you to detect issues before you generate production code. Running unit tests on a MEX function tests the instrumented code in MATLAB. Generated standalone code (static library or shared library) does not include the instrumentation and can include optimizations that are not present in the MEX code. To run unit tests on standalone code in a separate process outside of MATLAB, use software-in-the-loop (SIL) or processor-in-the-loop (PIL) execution. To use SIL or PIL execution, you must have Embedded Coder®.

This example shows how to:

  1. Create MATLAB unit tests that call your MATLAB function. This example uses class-based unit tests.
  2. Generate a MEX function from your MATLAB function.
  3. Run the unit tests on the MEX function.
  4. Run the unit tests on standalone code by using SIL.

Contents

Examine the Files

To access the files that this example uses, click Open Script.

addOne.m

The example performs unit tests on the MEX function generated from the MATLAB function addOne. This function adds 1 to its input argument.

function y = addOne(x)
% Copyright 2014 - 2016 The MathWorks, Inc.

%#codegen
y = x + 1;
end

TestAddOne.m

The file TestAddOne.m contains a class-based unit test with two tests.

  • reallyAddsOne verifies that when the input is 1, the answer is 2.
  • addsFraction verifies that when the input is pi, the answer is pi + 1.

For more information about writing class based-unit tests, see docid:matlab_prog.bufaqr6-1.

classdef TestAddOne < matlab.unittest.TestCase
    % Copyright 2014 - 2016 The MathWorks, Inc.
    
    methods ( Test )
        
        function reallyAddsOne( testCase )
            x = 1;
            y = addOne( x );
            testCase.verifyEqual( y, 2 );
        end
        
        function addsFraction( testCase )
            x = pi;
            y = addOne( x );
            testCase.verifyEqual( y, x+1 );
        end
    end
end

run_unit_tests.m

The file run_unit_tests.m calls runtests to run the tests in TestAddOne.m.

% Run unit tests
% Copyright 2014 - 2016 The MathWorks, Inc.

runtests('TestAddOne')

Run Unit Tests on a MEX Function with the MATLAB Coder App

To open the MATLAB Coder app, on the MATLAB Toolstrip Apps tab, under Code Generation, click the MATLAB Coder app icon.

To prepare for code generation, advance through the app steps.

  • On the Select Source Files page, specify that the entry-point function is addOne.
  • On the Define Input Types page, specify that the input argument x is a double scalar.
  • On the Check for Run-Time Issues step, enter code that calls addOne with representative input. For example, addOne(2). Perform this step to make sure that you can generate code for your MATLAB function and that the generated code does not have run-time issues.

For more complicated MATLAB functions, you might want to provide a test file for the Define Input Types and Check for Run-Time Issues steps. This test file calls the MATLAB function with representative types. The app uses this file to determine the input types for you. The test file can be different from the test file that you use for unit testing.

To generate the MEX function, on the Generate Code page:

  1. For Build type, specify MEX.
  2. Click Generate.

Run the unit tests on the generated MEX.

  1. Click Verify Code.
  2. In the field for the test file, specify run_unit_tests.
  3. Make sure that you set Run using to Generated code.
  4. Click Run Generated Code.

The app displays the test output on the Test Output tab. The unit tests pass.

Run Unit Tests After Modifying MATLAB Code

Modify addOne so that the constant 1 is single-precision. To edit addOne, in the upper-left corner of the app, under Source Code, click addOne.

To generate a MEX function for the modified function, click Generate.

To run the unit tests:

  1. Click Verify Code.
  2. Make sure that you set the test file to run_unit_tests and Run using to Generated code
  3. Click Run Generated Code.

The unit tests fail.

  • reallyAddsOne fails because the class of the output type is single, not double.
  • addsFraction fails because the output class and value do not match the expected class and value. The output type is single, not double. The value of the single-precision output, 4.1415930, is not the same as the value of the double-precision output, 4.141592653589793.

Run Unit Tests With Software-in-the-Loop Execution in the App (Requires Embedded Coder)

If you have Embedded Coder, you can run the units tests on generated standalone code (static library or shared library) by using software-in-the-loop (SIL) execution.

Generate a library for addOne. For example, generate a static library.

On the Generate Code page:

  1. For Build type, specify Static Library.
  2. Click Generate.

Run the unit tests on the generated code.

  1. Click Verify Code.
  2. In the field for the test file, specify run_unit_tests.
  3. Make sure that you set Run using to Generated code.
  4. Click Run Generated Code.

To terminate the SIL execution, click Stop SIL Verification.

Run Unit Tests on a MEX Function by Using the Command-Line Workflow

If you use the command-line workflow to generate code, you can run unit tests on a MEX function by using coder.runTest with a test file that runs the unit tests.

Generate a MEX function for the function that you want to test. For this example, specify that the input argument is a double scalar by providing a sample input value.

codegen addOne -args {2}

Run the units tests on the MEX function. Specify that the test file is run_unit_tests and that the function is addOne. When coder.runTest runs the test file, it replaces calls to addOne with calls to addOne_mex. The unit tests run on the MEX function instead of the original MATLAB function.

coder.runTest('run_unit_tests', 'addOne')
Running TestAddOne
..
Done TestAddOne
__________


ans = 

  1x2 TestResult array with properties:

    Name
    Passed
    Failed
    Incomplete
    Duration
    Details

Totals:
   2 Passed, 0 Failed, 0 Incomplete.
   1.0452 seconds testing time.

Run Unit Tests With Software-in-the-Loop Execution at the Command Line (Requires Embedded Coder)

If you have Embedded Coder, you can run the units tests on generated standalone code (static library or shared library) by using software-in-the-loop (SIL) execution.

Create a coder.EmbeddedCodeConfig object for a static library.

cfg = coder.config('lib');

Configure the object for SIL.

cfg.VerificationMode = 'SIL';

Generate code for the MATLAB function and the SIL interface.

codegen -config cfg -args {2} addOne

Run a test file that runs the unit tests with the SIL interface.

coder.runTest('run_unit_tests', ['addOne_sil.', mexext])

Terminate the SIL execution.

Click clear addOne_sil.