JaSST東海'12
のチュートリアル 「【テスト1年生シリーズ】はじめてのテスト技法
~テスト技法でバグ退治~」に参加してきました。(急遽スタッフwとして)
そこで同値分割・境界値分析について面白い話があったので書いておきます。
# 2012/12/01 最初に書いた解説が間違っていましたので修正しました。
# 秋山さん、指摘ありがとうございます。m(_ _)m
# 2012/12/02 さらに修正しました。
# 秋山さん、何度もありがとうございました。m(_ _)m
# やり取りはまとめましたので直接見たい方はそちらをどうぞ。まとめ
# 2012/12/03 もう少し修正しました。onポイントとoffポイントに関しては別途まとめようと思います。
# onポイントとoffポイントという言葉は知っていましたが、自分は誤解していました。。。
【問題】
入力の値が1~300(整数値)の値のときの同値分割・境界値分析はどうしますか??
同値分割クラスは以下になります。
①無効同値クラス:~ 0,
②有効同値クラス:1~300
③無効同値クラス:301~
②の有効同値クラスについて考えてみます。
仕様に書かれている1と300をonポイントと言い、境界を挟んで一番近い値である0, 301をoffポイントと言います。
境界値分析だと基本的にはonポイントとoffポイントの選択をしていきます。
今回の問題だと以下のようになります。テストケースは4ケース。
0(off) | 1(on) , 300(on) | 301(off)
※ただし、| を境界とする
これはJSTQBでも採用しているBeizer方式というようです。うーん初めて知りました。。。
このとき、コードは仕様に書かれている値(=onポイント)を使って以下のように書かれていると仮定します。(この仮定が重要!!)
if ((x >= 1) && (x <= 300)){
:
}
else{
:
}
何か間違えた場合にバグを検出することができるでしょうか?
if ((x > 1) && (x <= 300)){ ← [エラー] >=と>を間違えてしまった
:
}
else{
:
}
これは1を入力値としたテストケースで検出できますね。
ではこれだとどうでしょうか?
if ((x == 1) && (x <= 300)){ ← [エラー] >=と==を間違えてしまった
:
}
else{
:
}
>=と==を間違えてしまった場合は最初のテストケースだと0は無効、1は有効となりバグは検出できないですね。
(※この場合は上の方の境界値の300のケースで失敗することになりますが)
これを回避する一つの方法として中間値を取る方法があります。
これは以前の勉強会 で実施したハジ・ハジ・中間値の中間値に当たるものです。
②の有効同値クラスについてだと以下のようになります。テストケースは5ケース。
0(off) | 1(on) , 150(in), 300(on) | 301(off)
※ただし、| を境界とする
もう一つ回避する方法として、"3値の選択"というのがあるとのことです。
このときは仕様に書かれている値(=onポイント)を挟んで前後の値を取得することで3値ということになります。
今回の場合は問題より、1と300がonポイントになります。
②の有効同値クラスについて境界値分析するとonポイント+その前後で以下のようになります。テストケースは6ケースですね。
0(off) | 1(on) ,2(in), 299(in), 300(on) | 301(off)
※ただし、| を境界とする
この方法はJorgensenの方法(英国標準BS 7925-2で採用)というようです。こちらも聞くのは初めて。。。
これで>=を==としてしまったときでもエラーが検出されることになりました。
納得です!!
テストケース数が変わってきますので、どれを選ぶのかはちょっと悩みますね。
2値にするのか、2値+中間値も含めるのか、3値にするのか、是非考えてみてください。
どちらの方法を使うか、秋山さんの選択基準を教えてもらいました。参考までに。
********************************************************
どちらを使うか? ですが、私は、開発者本人が行うコンポーネントテストでは3値が良いと思っています(コーディングとテストで同じ間違えを犯すことを救うため)。
第三者がテストする際には仕様をきちんと読み直し2値で実施するのが良いと思っています。
********************************************************
今回この演習を通して、コードの書き方も大切だということを再認識しました。
同じことをやるのにもコードの書き方は沢山ありますね。
どれが理解しやすいのか、テスタビリティが高いのか、変更に強いのかを考える必要があると思います。
皆さんはどの書き方がいいと思いますか??
【その1】 仕様から想定するコード
if ((x >= 1) && (x <= 300)){
:
}
else{
:
}
【その2】無効の値を判定に使ったコード。整数なので上手くいく。
if ((x > 0) && (x < 301)){
:
}
else{
:
}
【その3】その1と逆で有効同値の処理をelseで実施しているコード
if ((x < 1) || (x > 300)){
:
}
else{ ← 1~300をelse内で処理・・・
:
}
【その4】 数値の順に判定しているコード
if (x < 1){
:
}
else if ((x >= 1) && (x <= 300)){
:
}
else if (x > 300){
:
}
【その5】if文の順序が変わると判定が変わってしまうコード
if (x <= 0){
:
}
else if ((x >= 0) && (x <= 300)){ ←0は上で引っかかっているので、入ってはこないが・・・
:
}
else if (x >= 301){
:
}