1.std::string/std::vector默认初始化导致行覆盖不上,请使用有参数初始化。
即
std::string camera_model_name;//不能行覆盖
std::vector<double_t> r_s2b_vec;//不能行覆盖
std::string camera_model_name{""};//行覆盖,但产生两个分支,仅覆盖1个
std::vector<double_t> r_s2b_vec{0LU};//行覆盖,但产生两个分支,仅覆盖1个
2.param omp可能导致无法覆盖
尽量不要使用
#pragma omp parallel for
可能导致之后的for循环无法行覆盖。
分支覆盖率产生分支的前提为该行已覆盖。
HOW TO提高分支覆盖率?--面向高覆盖率编程
-
避免抛出异常
其中,一可以通过增加测试用例来覆盖,二-七部分系gcc抛出异常导致,可以通过编译选项添加-fno-exceptions。但如果使用try-catch,那么编译不通过。
不添加-fno-exceptions:
添加-fno-exceptions:
上图展示了部分带有抛出异常的分支场景,包括printf/cout/string初始化/new/delete等,除delete[]外,通过关闭抛出异常,都不再产生额外分支。
2. 逻辑判断分支产生场景分析
1.if(condition) 如果条件为单独条件,那么会有两个分支,并只会覆盖其中一个。
2.for /while 除非初始判断就不满足,(即若p2 <0时),只会覆盖一个分支,其他情况执行循环体时两个分支都自动覆盖。
3.条件运算符 同if
4. 子条件复合
子条件复合时,会从左到右覆盖,如果满足一定条件时剩下分支不会覆盖。例如多个条件的或时,只要有个条件为true,其右侧分支不再覆盖,产生两个未覆盖分支,与操作的false同理。
单条件结果赋值时不会产生分支。
return 同理。
3. 简洁的子条件
尽量减少在判断中出现函数调用,以避免出现难以覆盖的新的分支。
如图所示,直接在判断中调用abs会多出两个分支,因次推荐子条件简洁化
函数调用与函数本身有无判断并不关,凡是多条件中产生函数调用均会产生两个分支,但多条件多次调用不会增加。
4.逻辑简单
尽量减少无意义的判断,或代码逻辑上不可能发生另一分支的情况
5. 拒绝用宏
尽量不要使用宏。
MCAM_SAFE_LOAD_PARAM:3/16
108 [ + - ][ + - ]: 10 : MCAM_SAFE_LOAD_PARAM(cameraSettings, "kc5", p.arr[j]);
[ + - ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
6.switch-case 与 if - else 的抉择
switch-case 共产生n+1个分支(n:case数量 1:default),但是一个样例只能覆盖1个分支,此处分支覆盖率1/(n+1)。
if-elseif 共2*n个分支,覆盖数视样例而定,最低1个,即第一if满足,最高n个,即前n-1个if elseif不满足,最后一个elseif满足。所以分支覆盖率1/(2n)~1/2。均值(n+1)/(4n)。
所以在仅有一个样例的情况下if else的分支覆盖率更高,(除非switch case漏了break)但实现分支全覆盖,都需要n个测试样例。
尽量不使用switch-case,改用if-else能够使分支覆盖率更高效。特别地,在对enum值的范围明确的情况下,如果不设置default值,那么会多一个无法覆盖的分支,并且if else if else可以减少两个分支的出现,即将最后一个取值设为else。