Contenido principal

polyspace.test.generateTests

R2026b

(Python) Generate C/C++ unit tests automatically

Since R2026b

Description

Generate Tests for Boundary Values or Coverage Objectives

testGenerationResults = polyspace.test.generateTests(proj, codeConfig, testOptions) generates tests for boundary values or coverage objectives within the default test suite of the project proj. Use codeConfig to specify options specific to the code under test and testOptions to customize the boundary testing strategy or code coverage objectives. If the project does not contain a default test suite and at least one test is generated, the test generator creates a default test suite.

example

testGenerationResults = polyspace.test.generateTests(___, Suite=testSuiteName) generates tests within the suite named testSuiteName in the project proj. If the project does not contain a test suite with this name and at least one test is generated, the test generator creates a test suite with name testSuiteName.

testGenerationResults = polyspace.test.generateTests(___, Suite=testSuite) generates tests within the test suite object testSuite in the project proj.

Generate Tests for Defects with Counterexamples

testGenerationResults = polyspace.test.generateTests(proj, staticAnalysisFile) generates non-regression tests from Polyspace® Bug Finder™ analysis results in staticAnalysisFile. The generated tests exercise the code under test with counterexamples produced by static analysis. The generated tests are contained within the default test suite of the project proj. If the project does not contain a default test suite and at least one test is generated, the test generator creates a default test suite.

example

testGenerationResults = polyspace.test.generateTests(___, Suite=testSuiteName) generates tests within the suite named testSuiteName in the project proj. If the project does not contain a test suite with this name and at least one test is generated, the test generator creates a test suite with name testSuiteName.

testGenerationResults = polyspace.test.generateTests(___, Suite=testSuite) generates tests within the test suite object testSuite in the project proj.

Input Arguments

expand all

Polyspace Platform project that contains the sources, include paths, and generated tests.

Name of the test suite in the specified project that contains the generated tests, specified as a string. If the project does not contain a test suite with this name and at least one test is generated, the test generator creates a test suite with name testSuiteName.

Test suite in the specified project that contains the generated tests, specified as a polyspace.project.TestSuite object. The test suite must belong to the project proj.

For function-based test generation, specifies options specific to the function such as the name of the function under test and constraints on the inputs. For script-based test generation, specifies options specific to the test script, including script body, preamble, setup and teardown code, and constraints on inputs.

Options to customize testing strategy, specified as either of:

Path to the file containing Polyspace Bug Finder analysis results, specified as a string with extension .psbf.

Output Arguments

expand all

Summary of generated tests, objectives, messages, options, and other project information, specified as a polyspace.test.TestGenerationResults object. This is a read-only object. To programmatically obtain information about the test generation results, explore the properties and subproperties of this object.

A polyspace.test.TestGenerationResults object contains these properties:

PropertyDescription
ProjectInfo

This property is a polyspace.test.ProjectInfo object, which has these properties: Path, Author, CreateDate, LastSaveDate, Description, and BuildConfigurationInfo.

  • The BuildConfigurationInfo property is a polyspace.test.BuildConfigurationInfo object with these properties: Name, Description, Toolchain, and Board.

Options

This property is a polyspace.test.TestGenerationOptions object, which has the following properties. Only one of these properties is nonempty, depending on the type of tests you generate.

Messages

This property is a polyspace.test.TestGenerationMessageList object. Each individual message in the list is a polyspace.test.TestGenerationMessage object that has these properties:

  • Msg — String containing the message.

  • Type — Type of the message, specified as one of these polyspace.test.MessageType enumeration members: NONE, WARNING, ERROR, FATAL_ERROR, INFO.

Tests

This property is a polyspace.test.GeneratedTestList object. Each individual test in the list is a polyspace.test.GeneratedTest object that has the SuiteName and TestName properties.

Objectives

This property is a polyspace.test.TestGenerationObjectiveList object. Each individual objective in the list is a polyspace.test.TestGenerationObjective object that has these properties:

  • Description — String describing the objective.

  • Status — Status of the objective, specified as one of these polyspace.test.ObjectiveStatus enumeration members: 'ALREADY_COVERED', 'JUSTIFIED', 'SATISFIED', 'UNREACHABLE', 'UNSATISFIED'.

  • Tests — Tests associated with this objective, specified as a polyspace.test.GeneratedTestList object.

Examples

expand all

Create boundary settings and generate a small suite that exercises boundaries with minimal combinations. Include both zero parameter values and off-by-one values in the generated tests.

Create the project, add your source files, and parse the code. Then create options and generate tests for the saturate_value function.

## Import modules
import polyspace.project
import polyspace.test
import os

## Create project
examples_path = os.path.join(polyspace.__install_path__, "polyspace", 
                            "examples", "doc_pstest", "getting_started_test_manager")

proj = polyspace.project.Project("myProject.psprjx")

## Add source files and include path
proj.Code.Files.add(os.path.join(examples_path, "algo.c"))
proj.Code.Files.add(os.path.join(examples_path, "saturate.c"))
proj.IncludePaths.add(os.path.join(examples_path))

## Parse code - returned object contains list of functions and other source code data
codeInfo = polyspace.project.parseCode(proj)

## Get function
func = codeInfo.getFunctionBySignature("int saturate_value(int)")

## Set global test generation options
bOpts = polyspace.test.BoundaryTestOptions()
bOpts.Mode = polyspace.test.BoundaryTestingMode.MINIMAL
bOpts.IncludeOffByOneValues = True
bOpts.IncludeZeroParameterValues = True

## Set function-specific test generation options
cfg = polyspace.test.FunctionTestGenerationConfiguration(func)

## Generate tests
testGenResults = polyspace.test.generateTests(proj, cfg, bOpts)

Generate tests that target full decision coverage for a function.

Create a project, add your source files, and parse the code. Then create options and generate tests for the saturate function. Finally, run the tests and verify that they have achieved full decision coverage for the saturate_value function.

## Import modules
import polyspace.project
import polyspace.test
import os

## Create project
examples_path = os.path.join(polyspace.__install_path__, "polyspace", 
                            "examples", "doc_pstest", "getting_started_test_manager")

proj = polyspace.project.Project("myProject.psprjx")

## Add source files and include path
proj.Code.Files.add(os.path.join(examples_path, "algo.c"))
proj.Code.Files.add(os.path.join(examples_path, "saturate.c"))
proj.IncludePaths.add(os.path.join(examples_path))

## Parse code - returned object contains list of functions and other source code data
codeInfo = polyspace.project.parseCode(proj)

## Get function
func = codeInfo.getFunctionBySignature("int saturate_value(int)")

## Set coverage objective to DECISION for test generation
cOpts = polyspace.test.CoverageTestOptions()
cOpts.Level = polyspace.project.CoverageMetricLevel.DECISION

## Set function-specific test generation options
cfg = polyspace.test.FunctionTestGenerationConfiguration(func)

## Set the coverage metric level to DECISION in active test configuration of the project
proj.ActiveTestConfiguration.CoverageOptions.Level = polyspace.project.CoverageMetricLevel.DECISION

## Generate tests
testGenResults = polyspace.test.generateTests(proj, cfg, cOpts)

## Run generated tests
testRunResults = polyspace.test.run(
      proj,
      ProfilingSelection=polyspace.test.ProfilingSelection.COVERAGE
)

# Read code coverage results
profilingResults = testRunResults.Profiling
coverageResults = profilingResults.Coverage

# Read decision coverage results
decisionCoverageResults = coverageResults.getCoverageInfo("decision")

# Loop through decision coverage details
# Raise exception if a decision in "saturate_value" is not fully covered
for details in decisionCoverageResults.Details:
    if (details.Function == "saturate_value") and not(details.IsCovered):
        raise RuntimeError("A decision in the target function is not fully covered.")

Inspect the contents of the decisionCoverageResults object. It shows full coverage for all decisions in the saturate_value function.

Run Polyspace Bug Finder analysis on your code to identify defects and generate example input values causing the defects (counterexamples). Then use Polyspace Test™ to generate C/C++ tests from these example input values.

You can run these tests in debug mode to understand how the input values lead to the defect. You can also retain these tests in your project as non-regression tests against further recurrence of the defect (static-analysis-guided test generation).

In this example, the source file example.c defines a function getRatio() with a division operation that is not protected against a division by zero. A second function checkRatio() calls getRatio() with inputs that do not preempt a possible division by zero in getRatio().

#include "decls.h"
double getRatio(double x, double y, int32_t z) {
    if  ((y > -100 && y < 100) && (z > 0 && z < 100))
    {
        return x/(y + z);
    } else {
        return 0;
    }
}

bool checkRatio(double x, int32_t y, int32_t z) {
    double ratio = 0.0;
    if (x > 0 && x < 1)  {
        ratio = getRatio(x, y / 10, z);
    }
    if (ratio < 0.5) {
        return 0;
    }
    return 1;
}

Run the polyspace-bug-finder (Polyspace Bug Finder) command to run static analysis on the example.c source file. Then generate tests to guard against the identified defects.

## Import modules
import polyspace.project
import polyspace.test
import os
import subprocess

## Run Polyspace Bug Finder Analysis to check for defects. Configure the analysis to:
## Enable stricter checks and provide counterexamples
## Consider all possible inputs for the "checkRatio" function
examples_path = os.path.join(polyspace.__install_path__, "polyspace", "examples", "doc_pstest", "defect_tests")
source_path = os.path.join(examples_path,"src","example.c")
polyspace_bug_finder_path = os.path.join(polyspace.__install_path__, "polyspace", "bin", "polyspace-bug-finder")

subprocess.run([polyspace_bug_finder_path, "-sources", source_path, "-checks-using-system-input-values", "-system-inputs-from", "custom=checkRatio"])

## Generate non-regression tests for defects with counterexamples
proj = polyspace.project.Project("myProject.psprjx")
proj.Code.Files.add(source_path)
proj.IncludePaths.add(os.path.join(examples_path, "src"))

testGenResults = polyspace.test.generateTests(proj, "ps_results.psbf")

Inspect the default test suite in the project. The suite contains one script-based test with the body 'checkRatio(0.5, -652, 65);'. This test exercises the checkRatio function with inputs that cause the expression x/(y + z) in the getRatio function to perform a division by zero.

Version History

Introduced in R2026b