以下の処理のテストケースを考えてみます。
メソッドexecuteFizzBuzz()
- 引数:整数を受け取ります
- 戻り値: 3の倍数の場合はfizz,5の倍数の場合はbuzz,3と5両方の倍数である場合はfizzbuzzを返します。1~100の範囲外である場合は常に0を返します
境界値テスト
境界値テストではOff-by-one error(後述)の対策である。
条件範囲の境界に最も近い2点をテストケースとして選ぶ
Off-by-one errorの対策
30メートルのフェンスを作り、3メートルごとにフェンスの支柱を立てる場合、必要な支柱の本数は何本か?
30÷3=10で10本と考えがちだが、実際に支柱は11本必要。
このような勘違いを一般的にOff-by-one errorと呼ぶ。
- 数値の選定ミス(開始を1,0どちらにするか。終端をn、n+1どちらにするか)
- 不等号のミス(< ,<=どちらをつかうのか)
のような範囲を扱う数値の勘定ミスによるバグは
- 一目でバグとわかりにくい
- 静的解析で発覚しないことが多い
- コンパイルエラーにならないことが多い
- エラーの多くは実行時まで見つからない
だから境界値を検査することには大きな意味がある。
境界値テストのケース
今回のテスト対象では範囲が1以上、100以下であり、範囲外の場合は0を返すため
- 0 (範囲外(未満)で最大)
- 1 (範囲内で最小値)
- 100(範囲内で最大値)
- 101(範囲外(多すぎ)で最小値)
この4種類を境界値のテストとする
同値クラステスト
同値クラステストでは同じ内容の処理となる値を同値クラス
に分割し、代表値を選んでテストケースを減らす工夫を行う。
同値クラステストのケース
処理結果をグループ分けし、代表値を一つ選んでテストする。
- fizzを返すもの (15の倍数を除く3の倍数) 例:99
- buzzを返すもの (15の倍数を除く5の倍数) 例:20
- fizzbuzzを返すもの (15の倍数) 例:45
- 範囲外で失敗するもの(小) 例:-1
- 範囲外で失敗するもの(大) 例:123
今回はこの5種を同値クラスとする。
※4,5は境界値テストで他の代表値を検査できているので
本来は実施しなくてもよい。
他
0は特別な数字なので、
数値を処理対象としているなら検査すべき。
最終的なテストケース
ケース番号 | 入力 | 出力 |
---|---|---|
1 | 0 (範囲外(未満)で外最大) | 0 |
2 | 1 (範囲内で最小値) | 1 |
3 | 100(範囲内で最大値) | buzz |
4 | 101(範囲外(多すぎ)で最小値) | 0 |
5 | 99(3の倍数) | fizz |
6 | 20(5の倍数) | buzz |
7 | 45(15の倍数) | fizzbuzz |
8 | -1(範囲外で失敗) | 0 |
9 | 123(範囲外で失敗) | 0 |
10 | 0(特別な数値) | 0 |
より実践的なケース
現場だとケースそのものを実行するのではなく、
更に同値クラスを排除した実行結果をエビデンスとして用意し、
テストケースと対応させて無駄な作業を省略しています。
ケース10は1と同じinput output なので排除可能です。(ケース1は境界値検証をしているので排除不可です)
ケース8はケース2と同値クラスなので排除可能です。
ケース9はケース4と同値クラスなので排除可能です。
ケース6はケース3と同値クラスなので排除可能です。
実行番号 | 入力 | 出力 |
---|---|---|
1 | 0 (範囲外(未満)で外最大) | 0 |
2 | 1 (範囲内で最小値) | 1 |
3 | 100(範囲内で最大値) | buzz |
4 | 101(範囲外(多すぎ)で最小値) | 0 |
5 | 99(3の倍数) | fizz |
6 | 45(15の倍数) | fizzbuzz |
ケース番号 | 入力 | 対応する実行番号 |
---|---|---|
1 | 範囲外(未満)で外最大 | 1 |
2 | 範囲内で最小値 | 2 |
3 | 範囲内で最大 | 3 |
4 | 範囲外(多すぎ)で最小値 | 4 |
5 | 3の倍数 | 5 |
6 | 5の倍数 | 3 |
7 | 15の倍数 | 6 |
8 | 範囲外で失敗(小さすぎる) | 1 |
9 | 範囲外で失敗(大きすぎる) | 4 |
10 | 0の入力確認 | 1 |
同値クラスを見つけて重複を除くことで実施回数が10個→6個に減らせました。
テスト結果を確認する人が各ケースがどのエビデンスと対応しているのかわかりやすいように示しておきましょう。