連載
» 2016年12月21日 11時00分 UPDATE

山浦恒央の“くみこみ”な話(90):猫でも分かるソフトウェアのテスト網羅(7):C2カバレッジは「裸の王様」 (1/3)

「制御パステスト」をテーマとする「猫でも分かるソフトウェアのテスト網羅」シリーズの第7回(最終回)では、前回に引き続き、パス・カバレッジの王者である「C2カバレッジ」の弱点を解説します。

[山浦恒央 東海大学 大学院 組込み技術研究科 非常勤講師(工学博士),MONOist]

1.はじめに

制御パステストは悩ましい ※写真はイメージです

 制御パステストは命令文や分岐に着目し、プログラムが実装された通りに動作するか確認する手法です。カバレッジは、プログラムの命令文や分岐の網羅をチェックして、これに関するバグを検出する制御パステストの手法です。パステストの代表的な基準が、C0、C1、C2カバレッジで、ホワイトボックステストの王様と言えます。中でも、C2カバレッジは、「最強のパステスト手法」、「パス網羅の王者」ですが、見ようによっては「裸の王様」です。命令語や分岐以外にも、バグはたくさんひそんでいます。

 前回は、C2カバレッジの欠点のうち4つを説明しました。今回は、C2カバレッジで網羅できない「ループ」「仕様のバグ」「無意味なコード」「割り込みやマルチタスク」を解説します。

2.C2カバレッジの弱点(その2)

 前回は、C2カバレッジの弱点として、「テスト項目数が爆発的に増大する」「結合したプログラム全体のカバレッジを網羅できない」「デバッグ用ツールが必須」「ブラックボックス・テストも併用する必要がある」の4つを挙げました。

 今回は、「ループを考慮しない」「仕様のバグを検出できない」「怪しいコードの検出を出来ない」「割り込みやマルチタスクのバグを検出できない」の4つを取り上げます。いずれも、「裸の王様」には難物です。

2.1 ループを考慮しない

 まっとうなプログラムの構造(専門用語で、「構造化プログラミング」)は、「連結(順次実行)」「分岐(if-then-elseの条件分岐)」「反復(繰り返し)」の3つに、「呼び出し(サブルーティンのコール)」を加えた4つでできています(*1)。

*1:今から40年前はアセンブリ言語が全盛で、私も、めちゃくちゃなプログラミングをしていました。別モジュールのど真ん中に入って20ステップほど実行して元のモジュールに戻るなんて当たり前でした。言ってみれば、真夜中に他人の家へベランダから侵入し、トイレの窓から帰るようなものです。今では、こんな乱暴狼藉を許さないため、全ての高級プログラミング言語では、その言語の文法、規則に従うと、必ず、構造化プログラミングになるよう「強制指導」しています。

 for文やwhile文に代表される繰り返し処理は、非常に効率が良いのですが、プログラムが複雑化する欠点があります。特に、ループのネストが三重以上になると、プロのエンジニアでもバグも見逃す可能性がありますし、可読性が著しく低下します。参照文献[1]によるとループのバグには以下の特徴があるそうです。

  • 影響度は高くない
  • メモリ境界エラー、ポインタ・エラー、ファイルの領域外アクセス引き起こすことが多い
  • 単体テストで検出するのが理想的

 ループのエラーは、単体テストフェーズで見つかる場合が大半ですので、早いうちからバグを見つけたいところです。C0、C1、C2を100%網羅すれば、ループのエラーを摘出できるでしょうか? C2を網羅している間にループを通れば可能でしょうが、基本的に摘出できません。ループのバグを検出したい場合は、ループに着目した特別のテストが必要です。例として表1の例を考えます。

  • 仕様1:従業員の給料を計算する。
  • 仕様2:従業員は1〜1万人までとする
int i, end;
scanf("%d" ,&end);
for (i = 1; i <= end; i++) {
	//給料計算処理
}
表1 ループの例題

 上記のプログラムは、ループ終了変数(end)を入力し、1からendまでを1ずつ繰り上げて計算するプログラムです。なお、具体的な給与計算処理は記述していません。かなりシンプルで、学部1年生でも記述できそうですが、テストは簡単ではありません。よくあるループテストの方法を表2に記述します。

テスト項目 確認する内容
0 従業員がいない場合が考慮されているか
1 1人の場合でも考慮されているか
代表的な数 代表的な値が考慮されているか
最大値−1 最大の境界条件が考慮されているか
最大値 最大の境界条件が考慮されているか
最大値+1 最大数以上が入力された場合が考慮されているか
表2 ループテスト例

 表2は、ループテストの基本的なテスト項目例です。ループの開始と終了の境界をテストするため、0、1、最大値、最大値±1をテストします(「最大値+1」は、むりやりパッチを当てて実施します)。加えて、代表的なループ数を入力し、正しい結果となることを確認すると良いでしょう。ループのネストや構造により、テスト項目は変わりますが、基本的には代表的な値、開始と終了の境界をテストします。

       1|2|3 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.