「制御パステスト」をテーマとする「猫でも分かるソフトウェアのテスト網羅」シリーズの第7回(最終回)では、前回に引き続き、パス・カバレッジの王者である「C2カバレッジ」の弱点を解説します。
制御パステストは命令文や分岐に着目し、プログラムが実装された通りに動作するか確認する手法です。カバレッジは、プログラムの命令文や分岐の網羅をチェックして、これに関するバグを検出する制御パステストの手法です。パステストの代表的な基準が、C0、C1、C2カバレッジで、ホワイトボックステストの王様と言えます。中でも、C2カバレッジは、「最強のパステスト手法」、「パス網羅の王者」ですが、見ようによっては「裸の王様」です。命令語や分岐以外にも、バグはたくさんひそんでいます。
前回は、C2カバレッジの欠点のうち4つを説明しました。今回は、C2カバレッジで網羅できない「ループ」「仕様のバグ」「無意味なコード」「割り込みやマルチタスク」を解説します。
前回は、C2カバレッジの弱点として、「テスト項目数が爆発的に増大する」「結合したプログラム全体のカバレッジを網羅できない」「デバッグ用ツールが必須」「ブラックボックス・テストも併用する必要がある」の4つを挙げました。
今回は、「ループを考慮しない」「仕様のバグを検出できない」「怪しいコードの検出を出来ない」「割り込みやマルチタスクのバグを検出できない」の4つを取り上げます。いずれも、「裸の王様」には難物です。
まっとうなプログラムの構造(専門用語で、「構造化プログラミング」)は、「連結(順次実行)」「分岐(if-then-elseの条件分岐)」「反復(繰り返し)」の3つに、「呼び出し(サブルーティンのコール)」を加えた4つでできています(*1)。
*1:今から40年前はアセンブリ言語が全盛で、私も、めちゃくちゃなプログラミングをしていました。別モジュールのど真ん中に入って20ステップほど実行して元のモジュールに戻るなんて当たり前でした。言ってみれば、真夜中に他人の家へベランダから侵入し、トイレの窓から帰るようなものです。今では、こんな乱暴狼藉を許さないため、全ての高級プログラミング言語では、その言語の文法、規則に従うと、必ず、構造化プログラミングになるよう「強制指導」しています。
for文やwhile文に代表される繰り返し処理は、非常に効率が良いのですが、プログラムが複雑化する欠点があります。特に、ループのネストが三重以上になると、プロのエンジニアでもバグも見逃す可能性がありますし、可読性が著しく低下します。参照文献[1]によるとループのバグには以下の特徴があるそうです。
ループのエラーは、単体テストフェーズで見つかる場合が大半ですので、早いうちからバグを見つけたいところです。C0、C1、C2を100%網羅すれば、ループのエラーを摘出できるでしょうか? C2を網羅している間にループを通れば可能でしょうが、基本的に摘出できません。ループのバグを検出したい場合は、ループに着目した特別のテストが必要です。例として表1の例を考えます。
int i, end; scanf("%d" ,&end); for (i = 1; i <= end; i++) { //給料計算処理 }
上記のプログラムは、ループ終了変数(end)を入力し、1からendまでを1ずつ繰り上げて計算するプログラムです。なお、具体的な給与計算処理は記述していません。かなりシンプルで、学部1年生でも記述できそうですが、テストは簡単ではありません。よくあるループテストの方法を表2に記述します。
テスト項目 | 確認する内容 |
---|---|
0 | 従業員がいない場合が考慮されているか |
1 | 1人の場合でも考慮されているか |
代表的な数 | 代表的な値が考慮されているか |
最大値−1 | 最大の境界条件が考慮されているか |
最大値 | 最大の境界条件が考慮されているか |
最大値+1 | 最大数以上が入力された場合が考慮されているか |
表2 ループテスト例 |
表2は、ループテストの基本的なテスト項目例です。ループの開始と終了の境界をテストするため、0、1、最大値、最大値±1をテストします(「最大値+1」は、むりやりパッチを当てて実施します)。加えて、代表的なループ数を入力し、正しい結果となることを確認すると良いでしょう。ループのネストや構造により、テスト項目は変わりますが、基本的には代表的な値、開始と終了の境界をテストします。
Copyright © ITmedia, Inc. All Rights Reserved.