境界値のバグは大きく分けて以下の5種類となります[1]。
閉括バグとは、境界が閉じているはずが開いていたり、開いているはずが閉じていたりする場合で、例えば、不等号のミスです(リスト2)。
//5歳より大きく、かつ、20歳未満は、入場料を1000円とする。 if (age >= 5 && age < 20){ //入場料1000円 }
リスト2は、閉括バグの例を示します。仕様では、「5歳より大きく、かつ、20歳未満は……」と書いてありますが、実装を見ると、「if (age >= 5 && age < 20){ 」のように「5歳以上、かつ、20歳未満は……」となっています。
下記に主な仕様記述とバグの例をまとめます(表1)。
仕様記述 | 正しい実装例 | 閉括バグの例 |
---|---|---|
60歳より大きい | if (age > 60) | if (age >= 60) |
60歳より小さい/60歳未満 | if (age < 60) | if (age <= 60) |
60歳以上 | if (age >= 60) | if (age > 60) |
60歳以下 | if (age <= 60) | if (age < 60) |
0〜5まで繰り返す | for (i = 0; i < 5; i++) | for (i = 0; i <= 5; i++) |
表1 閉括バグの例 |
表1は、仕様記述、正しい実装とバグの例を示したものです。不等号の記述ミスは圧倒的に多く、気を付けたいバグです。
左への境界移動とは、境界自体が左にずれたバグです(リスト3)。
//5歳より大きく、かつ、20歳未満は、入場料を1000円とする。 if (age > 4 && age < 20){ //入場料1000円 }
リスト3に、左への境界移動の例を示します。「5歳より大きく、かつ、20歳未満は……」となるはずが、実装上は、「if (age > 4 && age < 20){」のように「4歳より大きく、かつ、20歳未満は……」となっています。つまり、境界自体が左にずれ、4歳となりました。この場合、境界値の5歳は「入場不可」のはずが、「入場料1000円」となります。
右への境界移動とは、境界自体が右にずれたバグです(リスト4)。
//20歳以上、かつ、60歳未満は、入場料を2000円とする。 else if (age >= 20 && age < 65){ //入場料2000円 }
リスト4は、右への境界移動の例を示しました。上記の通り、「20歳以上、かつ、60歳未満……」となるはずが、実装上は、「else if (age >= 20 && age < 65){」のように「20歳以上、かつ、65歳未満は」となっています。境界が右にずれました。結果として、境界値の60歳が入場不可とならずに、入場料が2000円となります。
境界抜けのバグは、あるべき境界が抜けている場合です。この場合、境界値を入力した際に、異なる処理をするはずが同じになります(リスト5)。
//5歳より大きく、20歳未満の入場料は1000円とする。 if (age < 20){ //入場料1000円 }
リスト5に境界抜けのバグの例を示します。仕様では、「5歳より大きく、20歳未満……」となっていますが、実装では、「20歳未満は……」となっていることが分かります。この場合、境界値の5歳と6歳で出力結果が変わるはずが、どちらも入場料1000円となります。
余分な境界とは、文字通り余分な境界が存在する場合です(リスト6)。
//20歳以上かつ60歳未満は、入場料を2000円とする。 else if (age >= 20 && age < 55){ //入場料2000円 } else if (age >= 55 && age < 60){ //入場料1500円 }
リスト6には、余分な境界の例を示しました。例えば、以前のバージョンでは、「55歳から60歳は1500円」という仕様があったとします。仕様から「55歳から」を削除しましたが、実装上はそのままの場合、余分な境界が出現します。
この例では、出力結果が異なりますが、出力結果が同じ場合、バグに気付かない可能性があり、非常にタチの悪いバグとなります。
Copyright © ITmedia, Inc. All Rights Reserved.