代码覆盖率类型
如果您拥有 Embedded Coder®,Simulink® Coverage™ 可以对处于软件在环 (SIL) 模式、处理器在环 (PIL) 模式的模型以及受支持的自定义代码块内的代码执行多种类型的代码覆盖率分析。
语句覆盖率
语句覆盖率用于测量代码运行时执行的源代码语句的数量。使用这种类型的覆盖率来确定程序中的每个语句是否至少被调用过一次。
语句覆盖率的百分比由以下等式表示:
语句覆盖率 = (执行的语句数 / 总语句数) *100
语句覆盖率示例
以下代码片段中包含五个语句。为了实现 100% 的语句覆盖率,您至少需要进行一次使用正值 x 的测试、一次使用负值 x 的测试,以及一次使用 x 值为零的测试。
if (x > 0) printf( "x is positive" ); else if (x < 0) printf( "x is negative" ); else printf( "x is 0" );
条件覆盖率
条件覆盖率用于分析源代码中包含条件的语句。条件是 C/C++ 布尔表达式,其中包含关系运算符(<、>、<= 或 >=)、等式运算符(!= 或 ==)或逻辑求反运算符 (!),但不包含逻辑运算符(&& 或 ||)。这种类型的覆盖率用于确定每个条件是否都至少被计算出一次所有可能的结果。分支构造内的条件(例如 if、while 和 do-while)报告的是决策覆盖率而不是条件覆盖率。
条件覆盖率的百分比由以下等式表示:
条件覆盖率 = (执行的条件结果数 / 总条件结果数) *100
条件覆盖率示例
在以下表达式中:
y = x<=5 || x!=7;
有两个条件:
x<=5 x!=7
为了实现 100% 的条件覆盖率,您的测试用例需要对这两个条件都展示 true 和 false 结果。例如,在 x 等于 4 的测试用例中,这两个条件都为 true,而在 x 等于 7 的测试用例中,这两个条件都为 false。
布尔赋值语句
代码覆盖率会分析包含布尔值的赋值语句,并将它们作为一个条件进行报告。模型覆盖率仅分析赋值语句中的逻辑表达式,这意味着仅分析包含逻辑运算符(例如逻辑 AND (&&) 或逻辑 OR (||))的表达式。这种差异可能会导致模型覆盖率和代码覆盖率的结果不一致,有时可能导致代码覆盖率分析中出现无法满足的条件结果。
例如,假设有以下语句:
bool A = true;
在代码覆盖率分析期间,Simulink Coverage 会分析此语句的条件覆盖率。此语句在每个时间步都为 true,因此此语句的条件覆盖率为 50%,因为不会发生结果为 false 的情况。模型覆盖率不会分析此语句,因此这也导致了模型覆盖率与代码覆盖率结果之间的不一致。
决策覆盖率
决策覆盖率用于分析源代码中表示决策的语句。决策是由条件和一个或多个逻辑 C/C++ 运算符(&& 或 ||)组成的布尔表达式。分支构造(if/else、while 和 do-while)内的条件都是决策。决策覆盖率用于确定在总决策结果数中代码在执行期间所执行的结果数所占的百分比。使用这种类型的覆盖率来确定代码中的所有决策(包括分支)是否都被测试到。
注意
符合 DO-178C 的决策覆盖率定义与 Simulink Coverage 的定义不同。为了使决策覆盖率符合 DO-178C,在“配置参数”中,对于不包含 && 或 || 运算符的布尔表达式,请将结构覆盖率等级设置为条件决策。
决策覆盖率的百分比由以下等式表示:
决策覆盖率 = (执行的决策结果数 / 总决策结果数) *100
决策覆盖率示例
以下代码片段中包含三个决策:
y = x<=5 && x!=7; // decision #1 if( x > 0 ) // decision #2 printf( "decision #2 is true" ); else if( x < 0 && y ) // decision #3 printf( "decision #3 is true" ); else printf( "decisions #2 and #3 are false" );
为了实现 100% 的决策覆盖率,您的测试用例必须对每个决策都展示 true 和 false 结果。
修正条件/决策覆盖率 (MCDC)
修正条件/决策覆盖率 (MCDC) 用于分析在执行期间决策内的条件是否独立地影响决策结果。为了实现 100% 的 MCDC 覆盖率,您的测试用例必须展示:
决策内的所有条件都至少被计算出一次所有可能的结果。
决策内的每个条件都独立地影响决策的结果。
MCDC 覆盖率的百分比由以下等式表示:
MCDC 覆盖率 = (被计算到所有可能结果且影响决策结果的条件数 / 决策内的总条件数) *100
修正条件/决策覆盖率示例
对于这个决策:
X || ( Y && Z )
以下一组测试用例提供 100% 的 MCDC 覆盖率。
| X | Y | Z | |
|---|---|---|---|
测试用例 #1 | 0 | 0 | 1 |
测试用例 #2 | 0 | 1 | 0 |
测试用例 #3 | 0 | 1 | 1 |
测试用例 #4 | 1 | 0 | 1 |
为了证明条件 Y 和 Z 可以独立地影响决策结果,对于这些测试用例,条件 X 必须为 false。如果条件 X 为 true,则决策的结果已经为 true。因此,条件 Y 和 Z 将不会影响决策的结果。
限制
对于代码覆盖率,MCDC 仅限于包含 1000 个或更少逻辑组合的表达式。如果表达式包含超过 1000 个逻辑组合,Simulink Coverage 会分析 MCDC,但在达到 1000 个逻辑组合这一限制时会停止,然后显示警告,提示 MCDC 分析不完整。
圈复杂度
圈复杂度使用 McCabe 复杂度度量方法来衡量代码的结构复杂度。为计算代码的圈复杂度,代码覆盖率使用以下公式:
N 是代码中的决策数。on 是第 n 个决策点的结果数。对于每个 C/C++ 函数,代码覆盖率会将复杂度数加 1。
覆盖率示例
对于以下代码片段,圈复杂度为 3:
void evalNum(int x)
{
if (x > 0) // decision #1
printf( "x is positive" );
else if (x < 0) // decision #2
printf( "x is negative" );
else
printf( "x is 0" );
}
该代码包含一个函数,这个函数有两个决策点。每个决策点有两个结果。使用前面的公式,N 为 2,o1 为 2,o2 为 2。代码覆盖率使用包含这些决策和结果的公式,并为该函数加 1。此代码片段的圈复杂度为:
c = (o1 − 1) + (o2 − 1) + 1 = (2 − 1) + (2 − 1) + 1 = 3
关系边界覆盖率
关系边界代码覆盖率用于检查包含关系运算的代码。关系边界代码覆盖率度量与模型覆盖率度量一致,如关系边界覆盖率中所述。在进行代码覆盖率分析时,模型中的定点数和枚举值都是整数。
函数覆盖率
函数覆盖率用于确定在仿真期间您的代码中的所有函数是否都被调用过。例如,如果您的代码中有十个不同的函数,函数覆盖率会检查在仿真期间这十个函数是否都至少被执行过一次。
函数调用覆盖率
函数调用覆盖率用于确定在仿真期间您的代码中的所有函数调用点是否都被执行过。例如,如果在您的代码中函数被调用了二十次,函数调用覆盖率会检查在仿真期间这二十次函数调用是否都被执行过。