Contenido principal

polyspace.test.RelationalBoundaryInfo Class

R2026b

Namespace: polyspace.test

(Python) Review relational boundary coverage results

Since R2024b

Description

This Python® class contains relational boundary coverage results obtained from executing C/C++ tests. Depending on how you create the object, the results can show the relational boundary coverage for an entire project, a single file, or a single function.

Creation

Description

relBoundCoverageInfo = coverageResults.getCoverageInfo("relbound") loads relational boundary coverage results for the entire project:

example

relBoundCoverageInfo = coverageResults.getCoverageInfo("relbound", fileName) loads relational boundary coverage results for the file fileName (specified by full path or path relative to the current working folder):

example

relBoundCoverageInfo = coverageResults.getCoverageInfo("relbound", fileName, functionName) loads relational boundary coverage results for the file fileName and function functionName:

example

Properties

expand all

Total number of relational boundary outcomes to be covered, specified as an integer.

For example, consider a function with only one relational boundary:

void foo(int x, int y){
    //...
    if(x<y){
        //...
    }
}
The boundary outcomes to be covered for this function are:

  • x = y

  • x = y-1

  • x = y+1

Since there are three total outcomes, the TotalCount value for this function would be 3.

For more information on relational boundary outcomes, see Relational Boundary Coverage.

Number of relational boundary outcomes actually covered during test execution, specified as an integer.

For example, consider a function with only one relational boundary:

void foo(int x, int y){
    //...
    if(x<y){
        //...
    }
}
The boundary outcomes to be covered for this function are:

  • x = y

  • x = y-1

  • x = y+1

Suppose a single test with input values x=1,y=1. This test only covers one of the three possible outcomes, so CoveredCount would equal 1.

For more information on relational boundary outcomes, see Relational Boundary Coverage.

Number of uncovered relational boundary outcomes that you justified during review, specified as an integer.

For more information:

Details of relational boundary coverage, specified as a list of polyspace.test.RelBoundCoverageDetail objects with the following properties:

PropertyDescription
FileFile containing relational boundary that requires coverage.
FunctionFunction containing relational boundary that requires coverage.
IsCoveredWhether all three outcomes of the relational boundary are covered.
IsJustifiedWhether you justified the uncovered relational boundary outcomes.
RationaleRationale for justification, if you justified the uncovered relational boundary outcomes.
SourceLocation

Location of the relational boundary in the source code, specified as a polyspace.test.SourceLocation object with the following properties:

  • StartLine – Starting line number of the relational boundary.

  • StartColumn – Starting column number of the relational boundary.

  • EndLine – Ending line number of the relational boundary.

  • EndColumn – Ending column number of the relational boundary.

TotalCountTotal number of relational boundary outcomes.
CoveredCountNumber of relational boundary outcomes covered.
JustifiedCountNumber of relational boundary outcomes justified.
Outcomes

Details of relational boundary outcomes specified as a list of polyspace.test.CoverageOutcome objects, with each object in the list representing a relational boundary outcome. The object has the following properties:

  • IsCovered – Whether the relational boundary outcome is covered.

  • IsJustified – Whether the relational boundary outcome is uncovered but justified.

  • ExecutionCount – Number of times the relational boundary outcome occurs during test execution.

  • Rationale – Rationale for justification, if the relational boundary outcome is justified.

  • Text – Outcome of the relational boundary to be covered. This property has the value ">", "<" or "==".

Text

Text of the code that involves a relational boundary outcome. For instance, if the relational boundary outcome occurs through an if statement:

if (idx < MAXSIZE)
The Text property contains the string "idx < MAXSIZE".

Examples

collapse all

This example shows how to see an overview of relational boundary coverage after executing your C/C++ tests.

In general, you generate and manage Polyspace® Test™ results by using classes from the polyspace.project and polyspace.test modules. Before starting, make sure you can import these modules on a Python shell or in a Python script without errors. For more information, see Set Up Python API for Polyspace.

Import the required modules:

import polyspace.project, polyspace.test
import os

Add source files and xUnit test files to a project. This example uses some example source and test files available with a Polyspace Test installation. Instead, you can use your own sources and tests.

example_path = os.path.join(polyspace.__install_path__,"polyspace",
                            "examples", "doc_pstest", "coverage_data_collection")
proj = polyspace.project.Project("newProject")
proj.Code.Files.add(os.path.join(example_path,"src", "example.c"))
proj.Tests.Files.add(os.path.join(example_path,"tests", "test.c"))

Set the relational boundary coverage metric to true in the configuration of the project. To examine the details of relational boundary test results, the coverage metric level must be set.

coverageMetricLevel = polyspace.project.CoverageMetricLevel.CONDITION_DECISION
proj.ActiveTestConfiguration.CoverageOptions.Level = coverageMetricLevel
proj.ActiveTestConfiguration.CoverageOptions.RelationalBoundary = True
For more information on coverage metric levels, see Coverage level (-cov-metric-level).

Run the tests added to the project with code coverage computation enabled.

res = polyspace.test.run(
      proj,
      ProfilingSelection=polyspace.test.ProfilingSelection.COVERAGE
)

Print an overview of relational boundary coverage.

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

# Read relational boundary coverage results
relBoundCoverageResults = coverageResults.getCoverageInfo("relBound","example.c")

# Print relational boundary coverage overview
relationalCoveragePercent = ((relBoundCoverageResults.CoveredCount 
                             + relBoundCoverageResults.JustifiedCount)
                             / relBoundCoverageResults.TotalCount) * 100
print(f"{relationalCoveragePercent} %")

The function foo in example.c has 4 relational boundaries.

int foo(int x, int y)
{
    if (x < 0 && y>0)
        return 1;
    else if (x > 0 && y==0)
        return 2;
    else
        return -1;
}
Each relational boundary has 3 outcomes resulting in 12 total outcomes.

x < 0y > 0x > 0y == 0
  • x - 0 = 0

  • x - 0 = 1

  • x - 0 = -1

  • y - 0 = 0

  • y - 0 = 1

  • y - 0 = -1

  • x - 0 = 0

  • x - 0 = 1

  • x - 0 = -1

  • y - 0 = 0

  • y - 0 = 1

  • y - 0 = -1

Since only 1 out of 12 outcomes were covered in testing, the resulting coverage percent is 1/12=8.33%.

For more information on relational boundary coverage, see Relational Boundary Coverage

This example shows how to find the relational boundaries in the source code that were not covered or partially covered during test execution.

In general, you generate and manage Polyspace Test results by using classes from the polyspace.project and polyspace.test modules. Before starting, make sure you can import these modules on a Python shell or in a Python script without errors. For more information, see Set Up Python API for Polyspace.

Import the required modules:

import polyspace.project, polyspace.test
import os

Add source files and xUnit test files to a project. This example uses some example source and test files available with a Polyspace Test installation. Instead, you can use your own sources and tests.

example_path = os.path.join(polyspace.__install_path__,"polyspace", 
                            "examples", "doc_pstest", "coverage_data_collection")
proj = polyspace.project.Project("newProject")
proj.Code.Files.add(os.path.join(example_path, "src", "example.c"))
proj.Tests.Files.add(os.path.join(example_path, "tests", "test.c"))

Set the coverage metric level to CONDITION_DECISION and set the relational boundary coverage metric to True in the configuration. To examine the details of relational boundary test results, the coverage metric level must be set.

coverageMetricLevel = polyspace.project.CoverageMetricLevel.CONDITION_DECISION
proj.ActiveTestConfiguration.CoverageOptions.Level = coverageMetricLevel
proj.ActiveTestConfiguration.CoverageOptions.RelationalBoundary = True
For more information on coverage metric levels, see Coverage level (-cov-metric-level).

Run the tests added to the project with code coverage computation enabled.

res = polyspace.test.run(
      proj,
      ProfilingSelection=polyspace.test.ProfilingSelection.COVERAGE
)

Print the details of relational boundaries that were not covered during test execution.

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

# Read relational boundary coverage results
relBoundCoverageResults = coverageResults.getCoverageInfo("relBound", "example.c")
print("relBoundCoverageResults.Details is: ", relBoundCoverageResults.Details)

# Print information of relational boundary outcome tests by looping through the coverage details
for details in relBoundCoverageResults.Details:
    percentCoverage = ((details.CoveredCount + details.JustifiedCount) / details.TotalCount) * 100
    print(f"Relation: '{details.Text}' in {details.Function} ({details.File}, line {details.SourceLocation.StartLine})")
    print("Expected Outcomes: ")
    for outcome in details.Outcomes:
        print(outcome.Text, "isCovered: ", outcome.IsCovered)

If you use the example source and test files, you see several outputs in the format:

Relation: '<RelationText>' in foo (path\to\example.c, line number)
Expected Outcomes: 
<RelationalOperator> isCovered:  <True/False>
<RelationalOperator> isCovered:  <True/False>
<RelationalOperator> isCovered:  <True/False>
For instance:
Relation: 'y - 0' in foo (path\to\example.c, line 5)
Expected Outcomes: 
< isCovered:  False
== isCovered:  True
> isCovered:  False
Which means for the relational boundary located at line 5 of example.c:
    else if (x > 0 && y==0)
The following is true:

  • y - 0 = -1 is not covered

  • y - 0 = 0 is covered

  • y - 0 = 1 is not covered

For more information on relational boundary coverage, see Relational Boundary Coverage

Version History

Introduced in R2024b