ユニットテストにおけるテスト手法

仕事でPHPのユニットテストを書いている。普段はユニットテストの手法としてブラックボックステストを行っているが、他の方法も調べたのでメモを残しておく。
 

代表的なテスト手法

やみくもにテストを増やしても、費やした時間に対して効果的なテストをしているとは限らない。
ここで紹介する代表的なテスト手法に従ったテストを書くことで短時間で十分なテストを作ることが出来る。
 
ユニットテストには、主に大枠として以下の2つのテスト方針が存在する。

  • ホワイトボックステスト
  • ブラックボックステスト

 
以下より、それぞれのテスト方針の詳細とその中で行われるテスト手法を説明する。
 

ホワイトボックステスト

ホワイトボックステストとは、ソースコード中の文や分岐、条件などを実行してバグを見つけるテストである。実行してバグを見つけるので、どの文、分岐、条件も1回は実行する必要がある。つまり、ホワイトボックステストでは、テストで実行した文、分岐、条件の割合が、テストの進捗を計る指標となる。この割合を「カバレッジ率(網羅率)」という。
ホワイトボックステストでは、カバレッジ率が100%になるのに必要なだけテストケースを作成する。
また、テストで確認する対象(文、分岐、条件)により、ホワイトボックステストの指標は、ステートメントカバレッジ(命令網羅)、ブランチカバレッジ(分岐網羅)、コンディションカバレッジ(条件網羅)の3つに分類されている。
 

ステートメントカバレッジ(命令網羅)

ソースコード中にある全ステートメント(命令文)のうち、1回でもテストで実行されたステートメントの割合。ステートメントカバレッジの「ステートメント」とはコードの「行」のことである。ステートメントカバレッジでは「分岐」については考えず、if文がtrueであろうが、falseであろうが、とにかくその行が実行されれば良い。開発現場ではC0カバレッジと呼ばれる。
 

ブランチカバレッジ(分岐網羅)

ソースコード中にある全ブランチ(分岐)のうち、1回でもテストで実行された分岐の割合。分岐で条件全体が成立したとき(trueのとき)と不成立のとき(falseのとき)の両方が実行される必要がある。開発現場ではC1カバレッジと呼ばれ、ブランチカバレッジはステートメントカバレッジよりも強い評価基準となり,ブランチカバレッジが100%の場合は,必然的にステートメントカバレッジも100%になる。
 

コンディションカバレッジ(条件網羅)

分岐に設定されている1つ1つの条件について、成立したときと不成立のときの両方がテストで実行された割合。1つの分岐に複数の条件が設定されている場合、各条件ごとに実行の有無を確認する。一見するとブランチカバレッジと似ているが、定義は異なる。例えば、以下のようなテスト対象のコードがあるとする。

if(a == 0 && b < 0) {
……
}

この場合、a = 0b = 0のテストケースとa = 1b = -1のテストケースを作成してテストを行えば、コンディションカバレッジのカバレッジ率は100%になる。しかし、2つのテストケースともif文自体はtrueにならないので、ブランチカバレッジのカバレッジ率は100%にはならない。
 
これら以外にも更に強い評価基準を持ったホワイトボックステストの指標が存在する。しかし、強い評価基準であればあるほど、相対的にテストの作成には時間がかかるようになる。
 

ブラックボックステスト

ブラックボックステストとは、ある入力に対し、仕様通りの正しい結果が返されるかどうかを確認するテストである。ホワイトボックステストとは異なり、ブラックボックステストではソースコードを見ない。内部処理は考えず、入力とそれに対する結果(戻り値)を照らし合わせてテストの合否を判定する。
ブラックボックステストでは、次に挙げる「同値分割法」と「境界値分割法」を用いる。これらはどちらか一方を行えば良いのではなく、必ず両方とも行う必要がある。
 

同値分割法

プログラムが期待する入力値である「有効同値」とそれ以外の入力値である「無効同値」のそれぞれに代表値を用意し、それらを入力値としてプログラムを実行した結果を確認する方法。たとえば、有効同値が0以上かつ1000未満の場合、無効同値は0未満かつ1000以上になる。
 

境界値分割法

有効同値と無効同値の境界となる値を入力値としてプログラムを実行し、その結果を確認する方法。例えば、有効同値が0以上かつ1000未満の場合、無効同値は0未満かつ1000以上で、その境界値は-1、0、999、1000となる。
 

どのテスト手法を採用すればいいのか

ホワイトボックステスト、ブラックボックステストのどちらか片方だけ行っても十分なユニットテストとはいえない。テストをする観点がソースコードなのか(ホワイトボックステスト)、振る舞いなのか(ブラックボックステスト)で異なるためである。カバレッジ率が高くても振る舞いが間違っていたらバグとなり、同様に振る舞いが合っていてもカバレッジ率を意識しないとコードの中でテストをしていない箇所に気付くことが出来ず、バグを生んでしまう可能性がある。
 
とはいえ、我々がユニットテストにかけることが出来る時間は限られている。全てのテストケースをテストクラスで記述しよう、などと気負ったりせず、ある程度自分の納得するまでテストケースを記述したあとは、以降のテストでテストケースが必要になったときにテストケースを追加するように考えるほうが気が楽である。
 
 
以上
 
 
参考
書籍 プログラミング現場の単体テスト

Article written by

Comments are closed, but trackbacks and pingbacks are open.