ソフトウェアテスト - 単体テスト
ソフトウェアは、銀行ATMや自動改札機といった生活基盤の上で動作し、我々が便利な生活を過ごす上で欠かせない存在となっています。しかし、これらソフトウェアが不具合を起こすと、大きな社会的損失を招く恐れがあります。例えば、SuicaやPASMOといった交通系ICカードにもソフトウェアは組み込まれていますが、そのソフトウェアの不具合により自動改札機が停止し、数百万人もの乗客が足止めされたこともありました。従って、ソフトウェアの開発者は、さまざまな利用状況を想定し、期待通りに動作するかテストすることが重要となります。
ソフトウェアをテストするさまざまな手法がありますが、本稿では簡単のために、「単体テスト」を対象とします。単体テストとは、プログラムの個々の機能(例えば、関数やメソッド)を対象とするテストです。図1に、テスト対象プログラムの例を挙げます。このメソッドは、整数値xとyを入力としてx2-y2の計算結果を出力します。
図2に、このメソッドに対する3つのテストケースを示します。簡単のため、テストケースは対象プログラムを動作させる「入力」と動作結果を比較する「期待する出力」から成るとします。各テストケースでは、2行目に期待する出力、3行目に入力およびメソッド呼び出しが記載されています。例えば、テストケース1は、(x,y)=(1,0)を入力し、x2-y2=1となるかテストしています。さて、テストケース2やテストケース3とさまざまな入力・期待する出力が考えられますが、整数値空間すべてをテストすることは現実的ではありません。人手・時間といった限られた資源の中で、欠陥を検出するために適切なテストケースを設計し実行する必要があります。ここで問題です。
Q. 図2の3つのテストケースのうち、欠陥を検出するために最も適切なテストケースはどれでしょう?
テスト品質の測定 - ミューテーション解析
代表的なテスト品質の測定方法として、「網羅率(カバレッジ)」という考え方があります。これは、テストケースによって実行された対象プログラム部分(例えば、命令文や分岐)の割合を測定します。図2のテストケースはすべて、図1の対象プログラムに含まれるすべての命令文を実行するので、命令網羅率は100%を示します。このように、開発者はテストケースの網羅率を測定することで、その品質を定量的に見積もることができます。では、100%の網羅率を示すならば3つのテストケースはいずれも甲乙付けがたい適切なテストケースでしょうか?
ソフトウェア工学分野における研究成果では、次のことが示されています。
- 網羅率は、プログラムのテストされた部分を識別するために有用である。
- 低い網羅率は、テストスイート が不適切であることを示すだろう。
- 高い網羅率は、テストスイートが効果的であることは示さない。
ソフトウェアテストにおいて、開発者の主たる目的は、ソフトウェアに潜む欠陥を発見することです。しかし、テストケースが対象プログラムの欠陥部分を実行したからといって、必ずしも不具合は顕在化されないところに課題があります。そこで本稿では、テストケースの欠陥検出能力を効果的に測定するミューテーション解析を紹介します。
図3に、ミューテーション解析の概要を示します。ミューテーション解析では、「テスト対象プログラム」と「テストケース」を入力として、テストケースの欠陥検出能力を示す「ミューテーションスコア」を出力します。ミューテーション解析の手順は下記のとおりです。
- テスト対象プログラムに対して意図的に欠陥を埋め込み、欠陥を含むプログラム(ミュータント)を生成します。欠陥を埋め込む方法は、ミューテーション操作として定義されています。
- ミュータント上でテストケースを実行します。ミュータントは欠陥を含むはずなので、このテスト実行は失敗することが期待されます。失敗した場合、テストケースは意図的に埋め込まれた欠陥を検出できたことを示します。
- 生成されたミュータントに対して検出されたミュータントの割合を計算し、ミューテーションスコアとして出力します。カバレッジと同様に、開発者はミューテーションスコアを元にテスト品質を定量的に見積もることができます。
では、先ほどの例題プログラム(図1)にミューテーション操作を適用してみましょう。簡単なミューテーション操作として、四則演算子を置換することで欠陥を埋め込む方法があります(図4)。生成されたミュータントは欠陥を含むプログラムなので、テストケースを実行すると失敗することが期待されます。表1に、生成されたミュータントに対してテストケースを実行した場合の結果を、期待通り欠陥を検出したかどうかの観点で示します。
この結果から、テストケース2のみ、図4で意図的に埋め込まれた欠陥を2つとも検出できたことが分かります。従って、先の問題に対して、ミューテーション解析を用いて導き出した解答は次のとおりです。
A. 3つのテストケースのうち、テストケース2が欠陥検出能力が最も高く適切です。
以上のように、ミューテーション解析は、テスト対象プログラムに意図的に欠陥を埋め込むことで、テストケースの欠陥検出能力を効果的に測定します。しかし、埋め込まれた欠陥が現実的でない場合、テストケースがそういった欠陥を検出できたことに意味はありません。開発者が実際に作り得る欠陥を埋め込むことが重要となります。そこで、プログラミング言語やテスト対象などの特徴をうまく捉えたさまざまなミューテーション操作が定義されてきました。
続いて、Webアプリケーションのクライアントサイド技術であるAjaxに特化したミューテーション解析ツール・AjaxMutatorを紹介します。