組み合わせテストケース生成ツール 「PictMaster」 とソフトウェアテストの話題 -24ページ目

強い制約とサブモデルを用いてデシジョンテーブルを自動生成する

これまでこのカテゴリ(PictMasterでデシジョンテーブル)では、組み合わせテストツールであるPictMasterを使ってデシジョンテーブルを生成する方法を説明してきましたが、今回はこれまでの説明とは異なる全く新しい生成の方法を紹介します。この方法はこれまでの方法と比較して非常に簡単で間違いが起きにくい方法です。

説明の例としてある水族館の入場券の発券システムを取り上げることにします。この水族館の入場料は次の表で決められます。

1


この表より優先する以下の規定があります。

(1) 小学生以下、都内在住・在学の中学生は無料です。中学生は生徒手帳を持参してください。
(2) 障害者手帳・愛の手帳をお持ちの方と、その付添者原則1名は無料です。
(3) 65歳以上の方は、年令の証明となるものをお持ちください。

生徒手帳の提示のない中学生および年齢の証明となるものの提示のない65歳以上は一般の扱いとなります。生徒手帳、年令の証明となるものの確認と付添者1名の制限は切符売場窓口の係員が行ないます。

係員は発券システムの画面を操作して入園券を発券します。発券システムの画面を以下に示します。

1


係員が区分1から区分3を指定し、発券ボタンをクリックすることで規定の料金の入園券が発券されます。この発券システムにはユーザインタフェース上、以下の動作制限があります。

・ラジオボタンは各区分ごとにかならずどれか1つだけが選択状態となる。
・都内在住と都内在学のチェックボックスは中学生のラジオボタンを選択した場合に選択可能となる。

この動作制限のテストはこの発券システムのデシジョンテーブルテストとは別に行なうことになります。

デシジョンテーブルを自動生成する手順は次の通りです。

1.仕様をもとに条件(パラメータ)とその値およびアクション(入園料)を洗い出す。
2.制約表で各入園料を制約条件とし、その入園料となる必要最小限のパラメータの値の組み合わせを指定する。
3.同じ入園料となる必要最小限のパラメータの値の組み合わせが複数ある場合は、OR条件となるように右隣りの制約に同じ制約条件の色でそれを記入する。
4.サブモデルでアクションを除くすべてのパラメータを指定し、サブモデルの組み合わせるパラメータ数に指定したパラメータの数を記入する。
5.環境設定の組み合わせるパラメータ数に1を指定し、生成を行なう。

以上をもとにこの発券システムのデシジョンテーブルを生成するPictMasterのモデルを次に示します。

3


4


サブモデルを使用するのはアクションである入園料を組み合わせの対象外とするためです。どの入園料がどのパラメータの組み合わせに該当するかは制約表で指定します。

制約1では、生徒手帳提示の中学生の場合のみ都内在住と都内在学が選択可能であることを指定しています。この制約指定があることによって、制約2以降での制約指定が簡単になります。

このモデルの生成結果を次に示します。

5


テストケース数は56件となりました。このデシジョンテーブルは圧縮していないデシジョンテーブルです。圧縮したデシジョンテーブルは制約表に書かれています。この制約表で空欄となっているところにDon't Careを意味する「-」を記入すればそれが圧縮したデシジョンテーブルです。ただし、制約1があるのでそれが該当する欄には「No」が入ります。正確に言うと制約11に制約1の制約指定が入り、新たに制約12を設け、区分2を生徒手帳提示の中学生とします。

圧縮したデシジョンテーブルを用いる危険性についてはこれまで述べてきた通りです。どうしても用いたいのであればテスト対象の制御フローを把握し、それに合った圧縮を行なったデシジョンテーブルを用いる必要があります。

今回説明した方法は、アクションを制約条件とし、そのアクションとなる必要最低限の条件の値を制約対象として組み合わせテストツールで組み合わせ可能な組み合わせだけを生成する方法であり、従来の全組み合わせを作成してから個々の組み合わせごとにアクションを記入するという教科書的なデシジョンテーブル作成方法に比べて格段に簡単で間違いの起きにくい方法です。さらに制約表がそのまま圧縮したデシジョンテーブルとなる点でも全く新しい方法です。

また制約指定に「強い制約」を用いることによってテストケース数の爆発を防いでいます。同様に年齢や性別などのようにどれか1つだけが必ず真となる条件は、Yes/Noの2値で表すのではなく、それぞれの値をそのまま用いる多値で表すことによってもテストケース数の爆発を防いでいます。

デシジョンテーブルの圧縮でテスト漏れが起きるもっとも単純な例

これまでの記事で、圧縮したデシジョンテーブルでテストを行なうとテスト漏れが起きることを説明しました。今回はテスト漏れが起きるもっとも単純な例を取り上げてみます。

取り上げる例題は電話番号の発信者番号通知処理です。

電話をかけると通常は自分の電話番号が相手に通知されます。これを電話会社との契約によって通知しないようにすることができます。また相手の電話番号の前に特別なダイヤルを付加して電話をかけることによって、相手に自分の電話番号を通知するかしないかを指定することもできます。

この発信者番号通知処理の仕様は次の通りです。

1.電話会社との契約で「通知する」を選択していると自分の電話番号が相手に通知される。
2.電話会社との契約で「通知しない」を選択していると自分の電話番号が相手に通知されない。
3.電話をかける際に相手の電話番号の前に186を付加すると電話会社との契約にかかわらず自分の電話番号が相手に通知される。
4.電話をかける際に相手の電話番号の前に184を付加すると電話会社との契約にかかわらず自分の電話番号が相手に通知されない。

この仕様から発信者番号通知処理について次のルールが得られます。

1.通知する
 (1) 電話会社との契約が「通知する」でかつ付加ダイヤルなしで電話をかける。
 (2) 186を付加して電話をかける。
2.通知しない
 (1) 電話会社との契約が「通知しない」でかつ付加ダイヤルなしで電話をかける。
 (2) 184を付加して電話をかける。

このルールをもとに表1の圧縮したデシジョンテーブルが作成できます。実際には付加ダイヤルの種類には別のサービスの関係でこれ以外にもあるのですがここでは問題を単純にするためにこの2種類だけとします。

1


圧縮していないデシジョンテーブルは、「-」に具体的なすべての値を当てはめて表を拡張することで表2が得られます。

2


表1の圧縮したデシジョンテーブルをもとにその条件の順番にプログラミングすると図1のフローチャートとなります。

11


このプログラムを表1の圧縮したデシジョンテーブルでテストすると、網羅されない2つのルートが残るのでテスト漏れが起きます。このようにわずか2つの条件、2種類の結果しかない単純な仕様でもテスト漏れが起きることが分かります。テスト漏れが起きないのは図2のプログラムの場合ですが、テスト担当者がテスト対象に図2のプログラムを期待してテストを行なうのは高いリスクを犯していることになります。

4


これまでの説明ではプログラム言語の判定文レベルの話でしたが、実際のテストにおいてはこの判定文の部分が各機能ブロックに相当するとみなすこともできます。ある機能がいくつかの機能を呼び出し複雑な論理関係を処理して動作を決めるということはよくあることです。この場合はブラックボックスのテスト技法を使用することになります。ということは圧縮していないデシジョンテーブルでテストするということです。

デシジョンテーブルをテストで使用する場合は必ず圧縮していないデシジョンテーブルを使用する必要があります。ただし、プログラム構造が分っていて、どのような制御フローで処理するかが明確に把握できていて、その制御フローに合った圧縮を行なっているデシジョンテーブルを使用するならその限りではありません。

複雑な論理構造を持つソフトウェアのプログラミングに 圧縮したデシジョンテーブルは強力な味方

プログラミングする人の多くは自分がデシジョンテーブルを使ってプログラミングしていることを知らないのではないかと思います。機能仕様書に書かれている仕様を表現している表の多くは形式こそ少し違いますがその本質はデシジョンテーブルそのものです。もともとデシジョンテーブルはソフトウェアの仕様を分かりやすく表現する手段として用いられました。かつてはデシジョンテーブルからプログラムを自動生成する試みもあったようです。今では開発分野よりもテスト分野の方でテスト技法としてデシジョンテーブルがよく知られています。

複雑な論理構造を持つプログラミングを行なう場合は、圧縮したデシジョンテーブルがあるとプログラミングが格段にやりやすくなるうえにプログラミングミスも減らすことができます。機能仕様書に書かれている仕様を表現している表のデシジョンテーブルは圧縮したデシジョンテーブルです。もしこれが圧縮されていないデシジョンテーブルでプログラミングしようとするととても大変なことになります。プログラミングミスも頻発するでしょう。

デシジョンテーブルを使ってプログラミングする場合、デシジョンテーブルの条件の並び順が重要になります。前回の記事と同じ例を用いて説明しましょう。この仕様を以下に再掲します。

ある博覧会の入場料を決定する仕様は次のように定められています。

1.平日以外は2000円
2.平日は1600円
3.18歳未満は1400円
4.優待券を持参している人は1800円
5.優待券を持参している18歳未満は1200円
6.複数の条件に一致する場合は安い料金を適用する

圧縮していないデシジョンテーブルを表1に示します。この表の条件の順番には特に意味はありません。

1


次にこれを圧縮したデシジョンテーブルの例を表2に示します。

2


このデシジョンテーブルは条件が18歳未満、平日、優待券の順番で並んでいます。このデシジョンテーブルをもとにプログラミングするとたいていの人は図1のプログラムになるはずです。

3


では条件の順番を変えて表3のデシジョンテーブルをもとにプログラミングした場合はどうでしょうか。

4


Don't Careを表す「-」が含まれていない18歳未満の条件から先に書き始める人が多いと思いますが、中にはこの並びのままに図2のプログラムを書く人がいるかもしれません。

5


このプログラムを何も考えずに圧縮したデシジョンテーブルでテストするとテスト漏れが起きます。デシジョンテーブルには結果が5つしかないのにプログラムの結果ルートは1つ多い6つだからです。ではこのプログラムでテスト漏れが起きないデシジョンテーブルの圧縮はどうすればよいでしょうか。それはデシジョンテーブルで「-」となっている優待券の#3の部分にYesとNoの値を記入して表3-1のようにデシジョンテーブルを拡張して6つの結果を持つデシジョンテーブルを使うようにすればよいのです。

6


続いて条件の並びを変えて表4のデシジョンテーブルをもとにプログラミングした場合はどうでしょうか。

7


このデシジョンテーブルの条件の並び順のままにプログラミングすると図3のプログラムになります。このプログラムをテストするデシジョンテーブルはどのような圧縮方法をとったとしても圧縮したデシジョンテーブルではすべてテスト漏れが起きます。このプログラムの結果ルートが8つあるので、テストするには圧縮していないデシジョンテーブルを用いる必要があります。

8


さすがにこのプログラムほど分かりにくいプログラミングをする人は少ないと思いますが、いないとは言えません。いないと断定するのはギャンブルのようなものです。簡単で分かりやすく合理的なプログラムを書くには圧縮したデシジョンテーブルを用いるときにDon't Careの「-」を1つも含まない条件から先に書くようにします。

複雑な論理を扱うプログラミングではこのように必ず圧縮したデシジョンテーブルを使うことで格段に正確にプログラミングすることができるようになります。その一方で、テストにおいて圧縮したデシジョンテーブルを使うことはテスト漏れの危険が常に付きまとうということになります。

ではどうしてもテストケースを減らしたいので圧縮したデシジョンテーブルを使いたい場合はどうしたらよいでしょうか。その場合は、テスト対象のソースコードを解析し、各条件ごとにいくつの結果ルートを持ったプログラムであるかを把握し、それに合った圧縮を行なったデシジョンテーブルを用いればよいということになります。こうなると制御パステストと同等な完全にホワイトボックスのテスト技法となります。

デシジョンテーブルの圧縮でバグの見逃しが発生するとはどういうことか?

圧縮したデシジョンテーブルを使ってテストを行なうことの危険性については以前に説明しました。その時あげた例はあまり一般的ではなかったので、今回はより一般的に起きやすい例をあげてみることにします。今回取り上げる例はある博覧会の入場料を決定する仕様です。

ある博覧会の入場料を決定する仕様は次のように定められています。

1.平日以外は2000円
2.平日は1600円
3.18歳未満は1400円
4.優待券を持参している人は1800円
5.優待券を持参している18歳未満は1200円
6.複数の条件に一致する場合は安い料金を適用する

この博覧会の入場料を決定するデシジョンテーブルを作成することにします。

仕様から料金ごとのルールは次の通りとなります。

(1) 2000円
 平日でなくかつ18歳以上でかつ優待券を持参していない。
(2) 1800円
 平日でなくかつ18歳以上でかつ優待券を持参している。
(3) 1600円
 平日でかつ18歳以上。
(4) 1400円
 18歳未満でかつ優待券を持参していない。
(5) 1200円
 18歳未満でかつ優待券を持参している。

このルールをもとにして直接次のデシジョンテーブルが作成できます。

1


このデシジョンテーブルは結果に影響を与えない部分にはDon't Careを意味する「-」が記入されています。作成したデシジョンテーブルは圧縮されているので、これを圧縮していないデシジョンテーブルに変更します。やり方は「-」の部分にYesとNoを割り当て表を拡張します。そうすると次の圧縮されていないデシジョンテーブルが得られます。

2


デシジョンテーブルの作成方法として教科書的なやり方は、最初にすべての組み合わせを作成し(今回の場合は2の3乗で8通り)、各組合せごとに結果を記入し、最後に結果に影響を与えない複数の組み合わせを1つにまとめて圧縮する方法というです。こうした方法では表を圧縮する際に間違いが起こりやすこと、また条件が多いと組み合わせが膨大となってしまうという欠点があり、お勧めできません。

これで圧縮したデシジョンテーブルと圧縮していないデシジョンテーブルの2つが得られました。

ここでこの仕様をソフトウェアとして実装する場合を考えてみましょう。この仕様の実装方法は1つとは限りません。少なくとも4種類はあります。ここではこの仕様の実装例として次の3つのフローチャートを示します。

3



4



5


これらのソフトウェアのうち、最初のソフトウェアが判定文が最も少なく「合理的」なソフトウェアであるといえます。ですがプログラマが必ず「合理的なプログラミング」を行なうという保証はまったくありません。今回は、圧縮したデシジョンテーブルの条件が、18歳未満、平日、優待券という順番に並んでいるので、このデシジョンテーブルをもとにプログラミングする人のほとんどは最初のフローチャートのプログラミングをするだろうということは言えます。しかし、デシジョンテーブルを作らずにプログラミングに取り掛かる人のほうがはるかに多いと思います。そういう人の中で、2番目や3番目のソフトウェアでプログラミングする人が出る可能性は否定できません。

これらのソフトウェアを表1の圧縮したデシジョンテーブルでテストすると、最初のソフトウェアではテスト漏れは起こりません。5つのルールでソフトウェアのすべてのルートを網羅しているからです。しかし、真ん中と最後のソフトウェアではテスト漏れが起きます。圧縮したデシジョンテーブルではルールが5つしかないのに、真ん中のソフトウェアでは6つ、最後のソフトウェアでは7つのルートがあり、網羅されないルートが出てくるからです。一方、圧縮していないデシジョンテーブルではどのソフトウェアでもテスト漏れは起きず、すべてのルートが網羅されます。

デシジョンテーブルを使ってテストを行なう場合、ブラックボックステストにおけるテスト対象のソフトウェアがどのように実装されているかを事前に把握することはできません。したがってデシジョンテーブルを圧縮してテストを行なうということは、常にテスト漏れの危険がつきまとうということを肝に銘じておく必要があります。

テスト技法を解説した書籍やネット上の解説では、そのほとんどがデシジョンテーブルを圧縮することが当然のように書かれています。デシジョンテーブルを圧縮することがいかに危険なことであるか。このことは強調してもしすぎるということはありません。

ごく一部の書籍やネット上の解説ですが、デシジョンテーブルの圧縮では「処理順が重要なので開発側との協力が必要」などと書かれているものがあります。おそらく言いたいのは「デシジョンテーブルを圧縮する場合は、テスト対象のソフトウェアのプログラム構造に合わせてテスト漏れが起きないような形で圧縮しなければならない」ということだろうと思われます。そもそもデシジョンテーブルテストはブラックボックスのテスト技法だったはずです。それなのにこれでは圧縮したデシジョンテーブルでのテストは制御パステストと同様なホワイトボックスのテスト技法ということになります。

徹底したテストが行なえる複雑な論理関係を持ったデシジョンテーブルをPictMasterで生成する

先日、「原因結果グラフとCFD技法を比較する」という記事で複雑な仕様を持つ例題を取り上げて原因結果グラフとCFD技法を用いてデシジョンテーブルを作成しました。今回は同じ例題についてPictMasterを使用してデシジョンテーブルを生成する方法を紹介します。

原因結果グラフとCFD技法を用いて作成したデシジョンテーブルは、結果に影響を与えないと考えられる原因についてはその組み合わせを一部省略したものでした。このデシジョンテーブルでは徹底したテストを行なうことはできません。徹底したテストを行なうには組み合わせを省略しないデシジョンテーブルが必要ですが、手作業では煩雑な作業となります。そこで今回はPictMasterを用いて省略しないデシジョンテーブルを作成してみます。

例題をもう一度以下に示します。

例題の仕様

例題は、就業可能な最低就業年齢を判定する問題です。最低就業年齢は次の仕様で決定されます。

1. 使用者が、労働者として就業させることが可能な最低年齢は、満15歳に達した日以後の最初の3月31日が経過した者(義務教育終了者)である(労働基準法56条)。

2. 最低年齢に達しない者は労働基準法上「児童」と称され、原則として就業させることはできないが、例外として次の事業については行政官庁の許可を受けて使用することができる。

3. 行政官庁の許可を受けるには、児童の年齢証明書、児童の就学に差し支えがないことを証明する学校長の証明書、および親権者または後見人の同意書を様式第1号の使用許可申請書に添えて労働基準監督署に提出しなければならない(年少則1条)。

4. 使用者は、使用する満18歳未満の者について、その年齢を証明する戸籍証明書を事業所に備え付けなくてはならない。また、満15歳に達した以後の3月31が経過しない者を使用する場合、児童の就学に差し支えがないことを証する学校長の証明書および親権者または後見人の同意書を事業場に備え付けなくてはならない(労働基準法57条)。

これはかなり複雑な論理関係を持つ例題です。

パラメータと値の決定

最初にモデルのパラメータと値を決定します。必要となるパラメータと値には次のものがあります。

年齢
 満18歳以上, 満16歳以上~18歳未満, 満15歳, 満15歳未満       
今日が3月30日以前
 T, F       
児童の年齢証明書を提出       
 T, F       
学校長の証明書を労基署に提出       
 T, F       
学校長の証明書を事業所に提出       
 T, F       
使用許可申請書を提出       
 T, F       
戸籍証明書を提出       
 T, F       
親権者がいる       
 T, F       
後見人がいる       
 T, F       
同意書を労基署に提出       
 T, F       
同意書を事業所に提出       
 T, F       
就業可能       
 T, F       

「年齢」はどれか一つだけが真となるので、パラメータ年齢の値として定義します。原因結果グラフでのONE制約はこれで表現することができます。パラメータの就業可能は期待する結果なので組み合わせ対象からは除外します。詳しくはサブモデルで説明します。

その他のパラメータの値はすべてTとFです。原因結果グラフを作成した時は親権者と後見人のそれぞれについて労基署に提出と事業所に提出を原因ノードとしましたが、親権者と後見人のどちらか真となった方が書類を提出することになるので、今回は「親権者がいる」と「後見人がいる」とは独立に「同意書を労基署に提出」と「同意書を事業所に提出」をパラメータとすることで、組み合わせるパラメータの総数を前回の16個から11個に削減しています。

サブモデルの指定

パラメータの「就業可能」はデシジョンテーブルでのアクションに相当するので組み合わせ対象から除外します。これはサブモデルを使用することで可能となります。サブモデル欄にパラメータの「年齢」から「同意書を事業所に提出」までの11個を記入し、サブモデル欄の組み合わせるパラメータ数に11を指定します。そして環境設定の組み合わせるパラメータ数に1を指定します。こうすることで「就業可能」を除いたパラメータの全数組み合わせとなります。

制約の指定

例題の複雑な論理関係は制約表で表現することができます。例題のパラメータ数は11個あります。単純な全数組み合わせでは4×2×2×2×2×2×2×2×2×2×2=4096通りにもなります。このままでは扱うことができません。そこで組み合わせできない組み合わせを制約表で除外することにします。ただし、除外すると言っても普通のやり方では歯が立ちません。ここではいわゆる「強い制約」を用いることによって、全数組み合わせの件数を劇的に削減させるようにします。「強い制約」の意味については「強い制約、弱い制約」を参照してください。

PictMasterのモデル

以下にこの例題を解くPictMasterのモデルを示します。


1


2


3


4


5


ここで各制約は次の論理関係を表現しています。

制約1~2
 年齢が満18歳未満では親権者か後見人のどちらか一方が真となる。
制約3
 満18歳以上ではいかなる書類の提出も不要で無条件に就業可能である。
制約4
 満16歳以上~満18歳未満では「戸籍証明書を提出」が真であれば就業可能である。
制約5
 満16歳以上~満18歳未満では「戸籍証明書を提出」が偽であれば就業不可である。
制約6
 満15歳で「今日が3月30日以前」が偽で「戸籍証明書を提出」が真であれば就業可能である。
制約7
 満15歳で「今日が3月30日以前」が偽で「戸籍証明書を提出」が偽であれば就業不可である。
制約8
 満15歳で「今日が3月30日以前」が真で各書類の提出がすべて真であれば就業可能である。
制約9~15
 満15歳で「今日が3月30日以前」が真で各書類のどれか一つの提出が偽であれば就業不可である。
制約16
 満15歳未満で各書類の提出がすべて真であれば就業可能である。
制約17~23
 満15歳未満で各書類のどれか一つの提出が偽であれば就業不可である。

パラメータの「親権者がいる」と「後見人がいる」の行は空白にしておきます。ここの組み合わせは制約1~2の指定に従って生成されます。

生成されたデシジョンテーブル

以上のモデルで生成を行なった結果を次に示します。

6


生成されたデシジョンテーブルは行と列が入れ替わっており、そのままテストケースとして使える形式になっています。テストケース数は41件となりました。この表は見やすいようにExcelの並べ替えの機能を使って並び変えています。

制約指定に「強い制約」を用いたために、生成されたデシジョンテーブルは制約指定とよく似ています。異なるのは「親権者がいる」と「後見人がいる」の組み合わせが追加されてテストケース数が2倍に増えている点だけです。制約1~2を削除し制約指定で空白行となっている「親権者がいる」と「後見人がいる」にどちらか一方だけが真の値を指定することで21件のテストケースとすることもできます。こうした場合はデシジョンテーブルを生成する必要はなく、制約指定がそのままデシジョンテーブルになります。このように制約指定によって複雑な論理関係を持つデシジョンテーブルを簡単に生成できることがお分かりいただけたと思います。

このデシジョンテーブルを用いることで徹底したテストを行なうことができます。

これまで何回かPictMasterでデシジョンテーブルを生成する方法を紹介してきましたが、それらはアクションを結果表を用いて指定する方法でした。今回の方法はそれとは異なり、サブモデルを用いてパラメータとしてのアクションを組み合わせから除外し、制約指定でアクションの値を指定しています。この新しい方法もPictMasterでデシジョンテーブルを生成する上で有効な方法であることが今回分かりました。

ほとんどの組み合わせテストツールでは、非常に複雑な制約を指定することが煩雑な作業となるという難点があります。また各制約間の論理関係を把握することが難しいという欠点もあります。従ってこれまで組み合わせテストツールでデシジョンテーブルを作成するということを行なった例はないのではないかと思います。しかしPictMasterでは制約表という独特の制約指定方式のおかげで複雑な論理関係を持つデシジョンテーブルを手軽に生成することができます