メインコンテンツ

Calculate C/C++ Code Coverage Using Self-Managed Builds

Code coverage measures how much of your code is covered by existing test cases. Using Polyspace® Test™, you can measure code coverage of C/C++ code and add appropriate test cases to achieve your desired level of coverage.

The steps for calculating code coverage depend on your test build workflow:

  • If you author tests by using the Polyspace Test xUnit API and build them using your own toolchain, you can calculate code coverage by leveraging this build.

  • If you create tests interactively in a Polyspace Platform project or add your xUnit tests to a project, you can calculate code coverage in the user interface or automate this calculation at the command line or using the Python® API.

This example shows how to calculate C/C++ code coverage using self-managed builds. In this workflow, you use a toolchain you have already set up and do not require a Polyspace Platform project. For project-based workflows, see:

Example Files

To follow this tutorial, copy the folder <polyspaceroot>\polyspace\examples\doc_pstest\coverage_data_collection to a writable location. Here, <polyspaceroot> is the Polyspace installation folder, for example, C:\Program Files\Polyspace\R2026a.

The folder contains two subfolders:

  • src — This subfolder contains the file example.c with functions to test.

  • tests — This subfolder contains the file test.c with tests for the functions in example.c.

In the tutorial below, the GCC compiler (gcc command) is used as the toolchain for building C source code and tests. You can adapt this workflow as needed to other compilation commands. For more complicated build environments, see the following examples:

The tutorial uses <PSTUNIT_SOURCE>, <PSTUNIT_INCLUDE>, and <PSPROFILELIB> as shorthands for files and folders available with a Polyspace Test installation. For the full paths to the files and folders, see Set Up C/C++ Testing and Code Profiling Using Self-Managed Builds.

Calculate Code Coverage

To calculate code coverage, instrument source files and then compile the instrumented sources along with tests into an executable that provides code coverage data:

  1. First, ensure there are no compilation errors by compiling the source and test files. In a terminal, navigate to the coverage_data_collection folder and run:

    gcc src/example.c tests/test.c <PSTUNIT_SOURCE> -I <PSTUNIT_INCLUDE>
  2. Instrument the source file example.c and compile the instrumented version:

    polyspace-code-profiler -instrument -instrum-dir instrums -cov-metric-level mcdc -- gcc -c src/example.c

    This command uses gcc -c src/example.c to identify the source file for instrumentation. The source file is copied and instrumented for code coverage, injecting macros to track execution paths. For example, every condition in an if statement is surrounded by macros so that a true and false outcome of the condition is registered during test execution. The compile command is then run with the instrumented copy in place of the original source to create an object file example.o.

    Note that the -c flag with the gcc command tells the compiler to perform compilation only, ignoring undefined symbols that will be resolved at link time. If omitted, you see errors such as the following because you have not yet provided the definitions of the instrumentation macros:

    Undefined reference to 'psprofile_register_file'

  3. Compile the test file test.c along with the file pstunit.c available with a Polyspace Test installation (indicated below as <PSTUNIT_SOURCE>):

    gcc -c tests/test.c <PSTUNIT_SOURCE> -I <PSTUNIT_INCLUDE>
    This compilation step creates two object files, test.o and pstunit.o.

  4. Link the object files created in the previous step with a precompiled library provided with the Polyspace Test installation.

    gcc example.o test.o pstunit.o <PSPROFILELIB> -o testRunner
    The precompiled library in this step contains definitions of the code instrumentation macros.

  5. Collect coverage data from the test executable using this command:

    • Windows®:

      polyspace-code-profiler -run -instrum-dir instrums -results-dir results -- testRunner.exe
      

    • Linux®:

      polyspace-code-profiler -run -instrum-dir instrums -results-dir results -- ./testRunner.out
      

    This command uses the code instrumentation artifacts in the instrums folder and saves code coverage data in the results folder.

  6. Generate a readable HTML report from the collected coverage data using the following command:

    polyspace-code-profiler -report -html -report-dir reports results
    This command generates an HTML report in the reports folder based on the coverage data in the results folder.

  7. Review the HTML report to identify coverage metrics with unacceptable values and execution paths that are not covered by your tests. For details, see Improve or Justify Missing Code Coverage Results.

In this example, the source and test files were compiled in separate steps. You can also compile the sources and tests in a single step, limiting instrumentation to sources only:

polyspace-code-profiler -instrument -limit-instrumentation-to src -instrum-dir instrums -cov-metric-level mcdc -- gcc -c src/example.c tests/test.c <PSTUNIT_SOURCE> -I <PSTUNIT_INCLUDE>
The option -limit-instrumentation-to ensures that only files in the folder src are instrumented, not your test files.

Accumulate Code Coverage from Separate Test Executions

You can accumulate code coverage results from separate test executions and review them together.

Suppose your current folder contains two sets of sources and tests that you want to execute separately:

  • src/src1.c is tested using the test file tests/test1.c

  • src/src2.c is tested using the test file tests/test2.c

You can collect cumulative coverage over the two test executions as follows.

  1. On a command line, set the environment variable PSPROFILE_RESULTS_FILE to a binary file path, /tmp/coverageResults/output1.bin.

  2. Instrument the first set of sources for code coverage calculation and then link the instrumented source and test with a precompiled library provided with Polyspace Test.

    polyspace-code-profiler -instrument -limit-instrumentation-to src -instrum-dir instrums -- gcc -c src/src1.c tests/test1.c <PSTUNIT_SOURCE> -I <PSTUNIT_INCLUDE>
    gcc src1.o test1.o pstunit.o <PSPROFILELIB>
    

    For more information on the variables <PSTUNIT_SOURCE>, <PSTUNIT_INCLUDE> and <PSPROFILELIB>, see Set Up C/C++ Testing and Code Profiling Using Self-Managed Builds.

  3. Run the test executable generated in the previous step. The folder /tmp/coverageResults contains a file output1.bin with the coverage data from this execution.

  4. Reset the environment variable PSPROFILE_RESULTS_FILE to another binary file path, for example, /tmp/coverageResults/output2.bin

  5. Instrument the second set of sources for code coverage calculation and then link the instrumented source and test with a precompiled library provided with Polyspace Test.

    polyspace-code-profiler -instrument -limit-instrumentation-to src -instrum-dir instrums -- gcc -c src/src2.c tests/test2.c <PSTUNIT_SOURCE> -I <PSTUNIT_INCLUDE>
    gcc src2.o test2.o pstunit.o <PSPROFILELIB>
    
  6. Run the test executable generated in the previous step. The folder /tmp/coverageResults contains a second file output2.bin with the coverage data from this execution.

  7. Convert the coverage data in binary form into a Polyspace Test coverage result file (.psprof file):

    polyspace-code-profiler -convert -instrum-dir instrums -results-dir results /tmp/coverageResults
    The accumulated coverage data from the two files output1.bin and output2.bin in /tmp/coverageResults are converted into a single coverage result file (.psprof file) in the results folder. If you open this file in the Polyspace Platform user interface, you can see the coverage results for both the files src1.c and src2.c.

Alternatively, you can generate .psprof files from separate test executions and merge them using the -merge option of the polyspace-code-profiler command. For more information on the options -convert and -merge, see polyspace-code-profiler.

See Also

Topics