テストのカバレッジを楽して増やす検討
カバレッジを増やすにはテストを増やすのが一般的でしょうか。
テストを増やさずにカバレッジを増やせないか検討してみました。
(既にこのような考えがあれば、すでにあるよ!って言ってください)
今回考えた事:
コードにちょっとした仕掛けを入れて、if文の分岐を無理やり曲げて、C0カバレッジの%を増やしたい。
同じ実行だけど違う分岐ができないか
C++のコード、1~9までを全部通したい
#include <stdio.h>
/* ここに仕掛けを入れる予定 */
int func(int i){
printf("func %d passed\n",i);
return 0;
}
int mainfunc(){
int rtn = 0;
rtn = func(1);
if(rtn==0){
rtn = func(2);
if(rtn==0){
rtn = func(4);
}else{
rtn = func(5);
}
}else{
rtn = func(3);
if(rtn==0){
rtn = func(6);
if(rtn==0){
rtn = func(8);
}else{
rtn = func(9);
}
}else{
rtn = func(7);
}
}
return 0;
}
int main(){
for(int i=0;i<8;i++){
mainfunc();
}
return 0;
}
基本的に成功フローを流れるものだから、
なんとかしてif文を失敗に制御できないだろうか。
作戦:if文を2回に1回強制的に失敗させる
こういうマクロを考えてみました。
//=========================================
// 基本的には成功するのだから、たまに失敗させる
#include <string>
#include <map>
bool sw(const char* func, int l){
static std::map<std::string,int> bb;
std::string k = func;
k += "_" + std::to_string(l);
if(bb.count(k)==0){
bb[k] = 0; // init value
}else{
bb[k] = 1-bb[k];
}
//DBG//printf("L.%s %d.\n",k.c_str(),bb[k]);
return (bb[k]==0);
}
#define EEE sw(__func__,__LINE__) &&
//=========================================
if文の関数名と行数を使ってユニークなIDを作って、mapで通過回数を管理して、
偶数回目に通過したらreturn falseするような仕掛けです。0・1を繰り返しているため。
(IDについて、ファイル名も加味すればもっとユニークでしょうか。ファイル内で閉じる仕掛けになりそうなので、今回はこれで良しとしました)
元のプログラムの方は、コンパイル前に「if(」を「if(EEE 」に置換するようにします。
(ifの前が文字列でないとか、正規表現とかを駆使する必要があると思います。置換する場合は、コメント消してインデンターとかフォーマッターとかでキレイなコードにすると事故が少なくて簡単です)
int mainfunc(){
int rtn = 0;
rtn = func(1);
if(EEE rtn==0){
rtn = func(2);
if(EEE rtn==0){
rtn = func(4);
}else{
rtn = func(5);
}
}else{
rtn = func(3);
if(EEE rtn==0){
rtn = func(6);
if(EEE rtn==0){
rtn = func(8);
}else{
rtn = func(9);
}
}else{
rtn = func(7);
}
}
return 0;
}
結果・考察
1-9、全部通っているでしょうか

ifが3階層あるので、2^3で8回同じテストを流せば全部通ると思って、そうなりました。
(funcも1度通過したらprintしないようにすれば良かったです)
ifが3階層あるようなコードを書くのは稀だと思います。
if文で不正な入力や予期せぬエラーでスカッと抜けるようなコードの方が多いと思います。
if(変な入力){return 1;}
rtn = func();
if(失敗){return 2;}
rtn = func();
if(失敗){return 3;}
rtn = func();
if(失敗){return 4;}
return 0; // 0 が OK
こういう場合は、最初の1回だけ失敗する方が効率がよさそうです。
追記
・エラー埋込み法 とは違いますよね。 ・カオスエンジニアリング とも違いますよね。
・どちらかというと スタブ ですかね
スタブを活用することで、外部サービスの応答時間やエラーレスポンスをシミュレートし、
テストの多様性と信頼性を高めることができます。
Discussion