はじめに
初めまして。2023年にNRIネットコムに入社した山家谷です。 入社してから半年が経過しましたが、まだまだ分からないことだらけです。 とにかく他の方々が書いたコードを読んで、調べて、真似て書いてみるの繰り返しですね。
筆者の場合、研修期間を経て、配属部署に着任してからまず最初にした仕事が単体テストの作成でした。その中でカバレッジという言葉が頻繁に登場するので、今回はカバレッジについてまとめたいと思います。
カバレッジとは
カバレッジとは、テスト対象のプログラムがどの程度テストできているか(網羅できているか)の指標のことです。
日本語に置き換えると網羅率なので、こちらのほうが分かりやすいかもしれないです。
基本的にはパーセンテージが高いほど、そのプログラムが正常に動作することが網羅できている = 品質が保証されるということになります。
カバレッジの種類
カバレッジには、以下の4種類があります。
C0:命令網羅(ステートメント・カバレッジ)
C1:分岐網羅(ブランチ・カバレッジ)
C2:条件網羅(コンディション・カバレッジ)
MCC:複合条件網羅(マルチコンディション・カバレッジ)
これらのカバレッジをサンプルプログラムと照らし合わせながら紹介します。
C0:命令網羅(ステートメント・カバレッジ)
全ての命令文が1回以上実行されるようにテストすることを命令網羅といいます。C0と表されることもあります。
以下のサンプルプログラムを例にとると、4行目にある命令文が実行されればよいので、(x,y) = (1,1)のような1ケースのみで、命令網羅を満たす( = カバレッジが100%になる)ことになります。
public static void sample_method(int x,int y){ if(0<x && x<10){ if(0<y){ System.out.println("命令文"); } } }
テスト内容 | xの値 | yの値 | 0 < x | x < 10 | 0 < y | |
---|---|---|---|---|---|---|
1 | 命令文が実行される | 1 | 1 | 真 | 真 | 真 |
命令網羅は、命令文が1回以上実行されれば良いため、テストケースが少なくなりテスト作成にかかる時間が減る一方、分岐について考慮しないために網羅性が低く不具合を発見しにくいという特徴があります。
C1:分岐網羅(ブランチ・カバレッジ)
全ての分岐を1回以上通るようにテストすることを分岐網羅といいます。C1と表されることもあります。
以下のサンプルプログラムを例にとると、2行目の条件式(0<x && x<10)の真偽、3行目の条件式(0<y)の真偽を網羅するようにテストするので、(x,y)= (1,1), (1,-1),(-1,-)のような最低3ケースを用意する必要があります。
public static void sample_method(int x,int y){ if(0<x && x<10){ if(0<y){ System.out.println("命令文"); } } }
テスト内容 | xの値 | yの値 | 0 < x | x < 10 | 0 < y | |
---|---|---|---|---|---|---|
1 | 0<x && x<10が真、0<yが真 | 1 | 1 | 真 | 真 | 真 |
2 | 0<x && x<10が真、0<yが偽 | 1 | -1 | 真 | 真 | 偽 |
3 | 0<x && x<10が偽(このとき0<yは通らない) | -1 | - | 偽 | 真 | - |
分岐網羅が100%だと、自動的に命令網羅についても100%となります。
分岐網羅は、全ての分岐したルートを1回以上通るようにテストするため、前述した命令網羅よりも網羅性が高く不具合を発見しやすい一方、テストケースが多くなりテスト作成に時間がかかるという特徴があります。
C2: 条件網羅(コンディション・カバレッジ)
個々の条件式の真偽をそれぞれ1回以上含むようにテストすることを条件網羅といいます。C2と表されることもあります。
以下のサンプルプログラムを例にとると、2行目の0<xが真になるパターンと偽になるパターン、x<10が真になるパターンと偽になるパターン、0<yが真になるパターンと偽になるパターンがそれぞれ1回以上含むようにテストするので、(x,y) = (1,1), (1,-1),(11,-),(-1,-)のような最低4ケースを用意する必要があります。
public static void sample_method(int x,int y){ if(0<x && x<10){ if(0<y){ System.out.println("命令文"); } } }
テスト内容 | xの値 | yの値 | 0 < x | x < 10 | 0 < y | |
---|---|---|---|---|---|---|
1 | 0<xが真、x<10が真、0<yが真 | 1 | 1 | 真 | 真 | 真 |
2 | 0<xが真、x<10が真、0<yが偽 | 1 | -1 | 真 | 真 | 偽 |
3 | 0<xが真、x<10が偽(このとき0<yは通らない) | 11 | - | 真 | 偽 | - |
4 | 0<xが偽、x<10が真(このとき0<yは通らない) | -1 | - | 偽 | 真 | - |
分岐網羅が100%だと自動的に命令網羅も100%となりましたが、条件網羅が100%でも命令網羅・分岐網羅が必ず100%になるとは限りません。
別のサンプルプログラムを使って検証します。
public static void sample_method2(int x,int y){ if(0<x && 0<y){ System.out.println("命令文"); } }
上記のサンプルプログラムの場合、(x,y) = (1,-1),(-1,1)でテストすると、0<xと0<yが真または偽となるケースをそれぞれ1回以上含むようにテストできているので条件網羅は100%ですが、0<x&& 0<yが真となるテストケースがないため分岐網羅は50%となります。
MCC: 複合条件網羅(マルチコンディション・カバレッジ)
個々の条件式の真偽を、全ての組み合わせ通りテストすることを複合条件網羅といいます。MCCと表されることもあります。
以下のサンプルプログラムを条件網羅でテストする場合、2行目の0<xが真になるパターンと偽になるパターン、0<yが真になるパターンと偽になるパターンがそれぞれ1回以上含むようにテストするので、(x,y) = (1,1), (-1,-1)のような最低2ケースを用意する必要があります。
一方、同じサンプルプログラムを複合条件網羅でテストする場合、2行目の0<x、0<yがそれぞれ真になるパターンと偽になるパターン全ての組み合わせをテストするので、(x,y) = (1,1), (1,-1),(-1,1),(-1,-1)のような最低4ケースを用意する必要があります。
public static void sample_method2(int x,int y){ if(0<x && 0<y){ System.out.println("命令文"); } }
テスト内容(C2:条件網羅) | xの値 | yの値 | 0 < x | 0 < y | |
---|---|---|---|---|---|
1 | 0<xが真、0<yが真 | 1 | 1 | 真 | 真 |
2 | 0<xが偽、0<yが偽 | -1 | -1 | 偽 | 偽 |
テスト内容(MCC:複合条件網羅) | xの値 | yの値 | 0 < x | 0 < y | |
---|---|---|---|---|---|
1 | 0<xが真、0<yが真 | 1 | 1 | 真 | 真 |
2 | 0<xが真、0<yが偽 | 1 | -1 | 真 | 偽 |
3 | 0<xが偽、0<yが真 | -1 | 1 | 偽 | 真 |
4 | 0<xが偽、0<yが偽 | -1 | -1 | 偽 | 偽 |
複合条件網羅では全ての組み合わせ通りテストするため最も網羅性が高い代わりに、その分テストケースが非常に多くなるという特徴があります。
まとめ
簡単にですが、カバレッジについてご紹介しました。
先輩によると、実際の開発現場で命令網羅(C0)でテストすることはあまりないそうです。
実際の現場ではコストや重要度でどのレベルでテストするのかが決まり、特に金融関連や生命に関わるものなど重要度が高いシステムでは網羅率を上げるために複合条件網羅(MCC)でテストを実施することも多いとのことでした。
ちなみに筆者の場合、配属部署に着任してから最初に作成した単体テストは分岐網羅(C1)でした。
筆者も用語はなんとなく知っているけど……ぐらいの認識だったので、今回のブログ執筆を機にしっかり覚えたいと思います。
拙い文章ではありますが、単体テストを行うにあたり、(おそらく)目にする機会が多いカバレッジについて理解が深まれば幸いです!