ソフトウェアの品質を学びまくる

ソフトウェアの品質、ソフトウェアテストなどについて学んだことを記録するブログです。

デシジョンテーブル超圧縮の夢に破れて

『ソフトウェアテスト技法練習帳』の勉強会で、めちゃくちゃいい質問がありました。

その場で答えてはみたのですが、すごく大事な話だと感じたので、ブログ記事にしておきたいと思います。ただわたし自身の理解も足りていないかもしれないので、お気づきの点があればフィードバックお願いいたします。

3行まとめ

  • デシジョンテーブルテストは、「複数の条件を組み合わせた場合の動作」を検証する技術である。
  • 「組み合わせる前の単一条件の動作」は、デシジョンテーブルテストの前に検証しておく必要がある。
  • デシジョンテーブルで2つ目もカバーできると思っていると、痛い目に合うかもしれない。

デシジョンテーブルの超圧縮!?

対象の問題は、本書「2.3 紳士服店の割引率」。
問題を雑に簡略化するとこうなります。

以下の仕様に基づいて、デシジョンテーブルを書け。
「ワイシャツとネクタイを含めて7点以上買えば、7%引きになる」

単純には、以下のようになります。
7点以上⋀ワイシャツあり⋀ネクタイあり ならば、7%引き。それ以外は割引なしと。
特にヒネリはありません。

1 2 3 4 5 6 7 8
7点以上 T T T T F F F F
ワイシャツあり T T F F T T F F
ネクタイあり T F T F T F T F
割引7% T F F F F F F F

これに対して、以下の質問をもらいました。

「ワイシャツあり」「ネクタイあり」の条件を別々にせず、「ワイシャツとネクタイが入っている」という1つの条件にしてはいけないのか。

なるほど。これをヨシとすると、以下のようになります。

1 2 3 4
7点以上 T T F F
ワイシャツとネクタイあり T F T F
割引7% T F F F

なんと、テストケース数が半分になりました!

ただそんなうまい話があるわけもなく、何か失っているものがありそうです。何しろ、これを突き詰めていくと、これでもいいのですからね・・・。

1 2
7点以上でワイシャツとネクタイあり T F
割引7% T F

具体的なテストケースを考えてみると・・

さて、少し話が変わります。
デシジョンテーブルでテストケースを導出したとして、ではそのままテストができるでしょうか?

いいえ、必ずしもそうではありません。
たとえば最初のテーブルの#1のテストケース、「7点以上」という条件がTになっていますが、具体的には何点にしましょうか。また「ワイシャツあり」とありますが、ワイシャツは何点含めましょう。
てな感じで、実際にテストを行うにはもうワンステップ、テストデータの具体化が必要なわけです。

では、2つ目のデシジョンテーブル(以下再掲)のために、こんなテストデータを用意します。

1 2 3 4
7点以上 T T F F
ワイシャツとネクタイあり T F T F
割引7% T F F F
  • #1: ワイシャツ×3、ネクタイ×3、ソックス×4
  • #2: ソックス×10
  • #3: ワイシャツ×3、ネクタイ×3
  • #4: ソックス×3

もし実装が以下のようになっていれば、このテストはすべて通るでしょう。

7点以上 ⋀ (ワイシャツあり ⋀ ネクタイあり) → 割引7%

一方、以下のように実装が間違えまくっていても、このテストはすべて通ります

9点以上 ⋀ (ワイシャツあり ネクタイあり) → 割引7%

デシジョンテーブルで網羅的にテストをしたはずなのに、一体、何が悪かったのでしょうか・・?

ブレイクタイムに書かれた重要な注意書き

実はこの2.3のコラム欄「ブレイクタイム」に、こんなことがさらっと書かれています。

デシジョンテーブルを使ってテストをしたからといって、十分にテストをしたとは言えません。なぜなら、デシジョンテーブルは条件の組み合わせを網羅するものであり、個々の条件をテストするものではないからです。

これは、単体テスト→統合テスト→システムテストと、小さな範囲のテストを積み上げていくことに似ています。部品の組み合わせのテストをする前に、部品自体のテストをする必要があるということです。

では、先のデシジョンテーブル(以下再掲)を元に、部品である個々の条件を調べてみましょう。

1 2 3 4
7点以上 T T F F
ワイシャツとネクタイあり T F T F
割引7% T F F F

条件「7点以上」

「7点以上」という単一の条件自体が正しく動作するかを確認してみましょう。
この場合は、デシジョンテーブル上で「7点以上」の値だけが結果に影響を与えるテストケースを選んで、境界値テストをすることができます。

1 3
7点以上 T = 8点 F = 7点
ワイシャツとネクタイあり T T
割引7% T F

ここでもし実装が上述のように

9点以上 ⋀ (ワイシャツあり ネクタイあり) → 割引7%

と誤っていれば、#1のテストが失敗(割引7%がFになってしまう)で検知できることになります。

条件「ワイシャツとネクタイあり」

「ワイシャツとネクタイあり」という条件が正しく効いているのかの確認には、テストケース#1と#2を使います。

1 2
7点以上 T T
ワイシャツとネクタイあり T
ワイシャツあり ネクタイあり
F
ワイシャツあり ネクタイなし
ワイシャツなし ネクタイあり
ワイシャツなし ネクタイなし
割引7% T F

そう、デシジョンテーブルの中で1つの条件に丸めることで、一見テストケースが減ったように見えましたが、部品の確認のために結局、ワイシャツとネクタイのあるなしの組み合わせを個別に確認する*1とになるのです。

つまり、やるべき具体的テストケースの数は別に減っちゃいないということですねー。

まとめ

再掲。

  • デシジョンテーブルテストは、「複数の条件を組み合わせた場合の動作」を検証する技術である。
  • 「組み合わせる前の単一条件の動作」は、デシジョンテーブルテストの前に検証しておく必要がある。
  • デシジョンテーブルで2つ目もカバーできると思っていると、痛い目に合うかもしれない。

勉強会での質問を受けて、あらためて認識しました。これを説明しているところって、意外に少ない気がしましたが、どうでしょう*2

なお本稿は、ネモトノリユキさん、しましまさん、ブロッコリーさんにレビューいただきました。ありがとうございます。

追記 (2024/9/24)

秋山さんから以下のコメントをいただきました。

ここでいう「条件」とは、「7点以上である/ない」「ワイシャツがある/ない」「ネクタイがある/ない」の、各単一条件を指します。
判定とは、単一条件を組み合わせた結果、「割引がある/ない」という判定がどうなるかを指します。

Generated By Dalle

*1:なし/なしを省略する作戦はありうる

*2:ブロッコリーさんから、『ASTERセミナー標準テキスト』に近いことが書かれている、とコメントいただきました。確かに演習問題の方のファイルP.23に、以下の説明がありました。

それぞれの条件に対して同値分割法・境界値分析を適用する。