状態遷移のテストでは隠れた条件分け、アクション、遷移に気をつける

省略された条件分け

 某所向けのまとめです。状態遷移図ではたまに次のような条件分けされた遷移が出てきます。


f:id:goyoki:20120214212053p:image:w520


 画面遷移や全体的な設定の遷移など粒度・抽象度の大きい状態遷移を扱っていると、実際にはこうした分岐に以下のような複雑な条件やアクションが隠されていることがあります。


f:id:goyoki:20120214212054p:image:w520


 また図中に含まれない間接的な要素を含めれば、以下のようにより複雑な場合分けになっているかもしれません。


f:id:goyoki:20120214212046p:image:w520


 こうした隠れた条件分けは、テスト設計を行う際に注意しなければなりません。というのも、そういったものを見逃していると、隠れた遷移やアクションに起因するバグ、あるいは予期しない副作用等をテストで見逃す恐れが高まるためです。

省略された条件わけを明確化する

 例で挙げたような粒度・抽象度の大きい状態遷移は、複雑なソフトウェアを相手にすると扱わざるを得ない場面が出てきます。
 ただその際は最低限、前述のように隠れた条件分けやアクション、遷移パスをなるべく網羅的に抽出してテスト設計に反映させた方が安全です。それによりイベント・トリガの入力が網羅的にピックアップされ、大まかな状態遷移図でもある程度網羅的なテストを構築できるようになるためです。
 例えば前述のような詳細な条件分けがあれば状態遷移図に補記していくべきですし、複雑な場合は下図のようにデシジョンテーブルや入出力表を図に結びつけてしまってもよいでしょう。


f:id:goyoki:20120214220441p:image:w520

さらに隠れた状態遷移や条件わけをピックアップする

 なお隠れた条件分けやアクションはガード条件の部分のみあるわけではありません。
 例えば以下のような場合:


f:id:goyoki:20120214213110p:image:w520


 入力の判定処理等の形でありがちですが、上図には以下のような条件分けが隠されている場合があります。


f:id:goyoki:20120214212050p:image:w520


 こうしたものも前述の通りピックアップしておくべきです。特に隠れた条件分けにアクションが含まれていればテストケースの追加がしばしば必要になります。
 次に以下のような場合:


f:id:goyoki:20120214212047p:image:w520


 画面遷移等でありがちですが、これも以下のような隠れたアクティビティが含まれている場合があります。これも同様に注意すべきです。


f:id:goyoki:20120214213305p:image:w520


 また今回言いたいことから少し離れますが、以下のような場合:


f:id:goyoki:20120214212049p:image:w520


 ここでキャンセルが非同期処理だと、「アクションA、アクションBを両方実行せずにキャンセル」「アクションAのみを実行してキャンセル」「アクションA、アクションB両方を実行してキャンセル」の3パターンを取りえる場合があります。割り込み処理等でありえる事例です。
 ただこうした例に対しては、テスト設計で苦労するより、設計でロックなど適切な非同期処理を実装してバグの可能性を減らす対処の方がしばしば妥当な対応策になります。

テスト設計の流れ

 なお留意点として一応触れておきますが、上記のような隠れた条件わけ・状態遷移のピックアップは、テスト分析・テスト設計の手間を増やすことはあっても、テスト実行の手間を増やすとは限りません。よりミスのないテスト設計をするための対策であり、例えばテストの規模を変えずにテストケースをより洗練させるといったことも実現できます。
 具体的には「詳細にピックアップした条件分けや状態遷移は0スイッチカバレッジで検証し、元々の主要な状態遷移はそれ以上のカバレッジで検証する」「大まかな状態遷移でテスト設計し、その後テスト実装の際は、詳細な条件を漏れなく振り分けて全体で被覆網羅されるようにする」といった選択肢がとれるようになります。