見出し画像

第95回: 状態遷移テスト(前編)

≡ はじめに

ASTERセミナー標準テキスト」の108ページについてです。

前回は、デシジョンテーブルの実践編について書きました。今回は状態遷移テストの基礎について書きます。

「状態遷移テスト」というと、画面を切り替えたときに入力したデータが保持されているか(もしくは、クリアされているか)といったことを確認するために、“画面を行ったり来たり彷徨う”テストで使用することが多いようです。

彷徨ってばかりいては、同じ画面を同じ方法で何度も開く一方で、一度も開いたことが無い画面が残ったりするのでよろしくありません。そこで、テスト技法を使うことで必要最小限のテスト回数で、無駄なく漏れなく、いい感じに画面移動したいというニーズがあります。

他にも、例えば、自動販売機で、釣銭が無いときに、「釣銭切れランプがついているか?」であるとか、「200円を投入してから、140円の購入ボタンを押したらどうなるか?」といった、“事前に「ある条件」にセットしておいてから、入力を与える”テストで使用します。

自動販売機の例は、彷徨う必要が無いので、前回学んだデシジョンテーブルテストの範囲(応用)で行うこともあります。
応用というのは、デシジョンテーブルの条件を事前条件(Pre-condition)と入力(Trigger)に分けて表記することによって、入力の順番を表現するなどです。

画面遷移や自動販売機の場合、テスト対象を状態遷移モデル(状態遷移図等)で表現し、その状態遷移モデルを網羅するテストを作ることが多いので、「状態遷移テスト」をモデルベーステストのひとつと認識している人もいます。

もっと単純に、仕様書にステート・マシン図(UML2.0で定義された、state machine diagram)が設計書に描いてあったときに、その図を網羅するテストを作成するテスト技法のことを「状態遷移テスト」と呼ぶと考えている人もいらっしゃいます。

これらは、どれも間違いではありません。しかし、一つひとつの事例で覚えておくのは大変ですし、ちょっと見た目が変わっただけで、応用が利かずに使わないというもったいないことが起こりがちです。

そこで、今回は、状態遷移テストの基礎固めをしたいと思います。


≡ デシジョンテーブルテストだけではだめなのでしょうか?

素朴な疑問として、

同値分割法と境界値分析は一つのパラメータの範囲の話だから、複数のパラメータの組合せをテストするデシジョンテーブルテストが必要なのは分かる。
しかし、ソフトウェアはつまるところ所与のデータ(入力)を処理するだけなのだから条件を与える順番を考慮したデシジョンテーブルテストを用いたらどんなソフトウェアテストであっても十分にテストを記載可能なのでは?

と思われたことはないでしょうか?

可能か不可能かで言えば、可能です。昔の話となりますが、JaSSTのセッションで「状態原因」を条件と見なすことで解決している説明もあります。

でも、「ステート・マシン図」から「状態原因」を抽出してデシジョンテーブルを作ることは大変ですし、できたとしても、N-スイッチテストのような複数の状態遷移パスを作ることはとても困難です。

デシジョンテーブルで、処理の順序を表現することが難しいからです。
また、“ある状態からある状態へしか遷移できない”という発想に立てば、非常に沢山の制約がある組合せなのでデシジョンテーブルでは作成困難と考えても構いません。


≡ 何がカギなのか

上に書いた「ソフトウェアは入力を処理するだけなのだからデシジョンテーブルで十分記載可能」と思っていたのは20年くらい前の私です。

その後、色々と考えたのですが、「ソフトウェアの振る舞いは入力で決まる」は、その通りなのですが、入力には、いくつか種類があって、それごとにテストを考えると良いことに気が付きました。

入力の種類は、FRAM(The Functional Resonance Analysis Method:機能共鳴分析手法)が定義している機能の6つの要素で示された5つの入力の種類分割が分かりやすいと思ます。

6つの要素のうちのひとつは出力です。

画像1

この図の中央にある6角形がFRAMでモデル化した機能です(丸文字まで)。
その周りのカラフルなところは、それぞれの要素の位置付けがわかりやすいように、私が書き加えたものです。

FRAMでは、機能は5つの入力(入力I、前提P、資源R、時間T、制御C)を受けて、1つの出力(出力O)を出すという、6つの要素をモデル化しています。

FRAMでは、このモデルで機能を表現して、その機能と機能を結びつけることで、より深く機能と機能が共鳴する仕組みをモデリングしています。
今回はFRAMの回ではないので、その話はここではしません。
HAYST法のラルフチャートでは、入力、状態、ノイズ、アクティブノイズ、出力の5つの要素で機能をモデル化しています。FRAMとの対応は、
 ・ 入力:入力I
 ・ 状態:前提P、資源R
 ・ ノイズ:資源R、時間T、制御C
 ・ アクティブノイズ:FRAMに無し
 ・ 出力:出力O
となります。

※ 資源Rが状態とノイズの両方に出ているのは、資源のうち、初期に必要な資源(でかつ動作中にあまり変わらない資源)を状態に、動作中に変化し振る舞いに影響を与える資源(メモリの枯渇等)をノイズに分けているからです。こちらについては、「わかんない」と言われることが多いので、そのうち、なんとかしたいと思っています。

話を戻します。テスト条件を見つけるときのカギのひとつは、入力を種類別に分けて考えることだと思っています。ラルフチャートよりもFRAMの方が分かりやすいので、そちらで説明します。

FRAMでは、機能は5つの入力(入力I、前提P、資源R、時間T、制御C)を受けて、1つの出力(出力O)を出す6つの要素モデル化しています。

と書きました。
まず、“入力Iが(振る舞いや)出力Oに与える影響”を確認するためにデシジョンテーブルテストが有効です。

厳密にいうと、FRAMの入力Iは機能を動かし始めるTriggerなのですが、それは、FRAMが大きな意味で機能を捉えているためだと思うので、ここでは、普通に、デシジョンテーブルの条件を入力と考えていただいて大丈夫です。

次の入力の種類である“前提Pが振る舞いや出力Oに与える影響”を確認するために有用なテストは何でしょう? 私はこれが状態遷移テストだと考えています。

残りの、資源R、時間T、制御Cについてですが、資源Rに着目したテスト技法は、にしさんのリソースパステストかと思います。

時間Tと、制御Cに着目したテスト技法はモデルチェッキングの一部にあるような?、無いような?という感じです。

タイミングと割り込みに対する体系的で網羅的なテストは人の力では無理で設計時に発生個所を局所化するアーキテクチャーを採用して、テストするときには、ランダムにたたく(=自動化)しかないような気がしています。上手い方法があれば、教えてください。


≡ 「状態」の正体

結論から書けば、「状態は、前提Pのことで、前提Pとはソフトウェアで言えば“状態変数の値の組合せ”」です。

架空の物語なのですが、こんな奇妙な現象について想像してください。

走行ラインを超えると、警告メッセージを出す自動車の機能があったとする。概ね期待通りに機能するが、ハザードランプを点滅させていると、走行ラインをオーバーしても、警告メッセージが出ない。

という振る舞いです。「警告メッセージが出ない」のは安全にかかわりますので、直さないわけにはいきません。

この原因は、ソフトウェアが、ハザードランプの点滅をウィンカー(方向指示器)の点滅と誤認したことによります。

ウィンカーはそもそも、右折・左折、そして、車線変更などの走行ラインを超えるという情報を後続車や周囲に伝えることが目的ですから、ウィンカーが点滅中に、その方向に走行ラインを超えても警告メッセージは出してはいけません。一方で、ハザードランプは緊急事態を伝えることが目的であり、車線変更に限りません。

さて、もう一段階深掘りをしてみます。なぜ「ソフトウェアは、ハザードランプの点滅をウィンカーの点滅と間違えた」のでしょうか??
その理由は、どちらも同じランプを使っていますので点滅中は同じ変数が“ON”となっていたからです。

つまり、
 ハザードが点滅中の状態  = 変数Xが“ON”
 ウィンカーが点滅中の状態 = 変数Xが“ON”
だったので、変数Xの値のみを見ていたソフトウェアは警告メッセージを出さなかったというわけです。

ここまで、分かれば、ハザードのときには左右のウィンカーの点滅状態を保持する変数が左右共に“ON”である仕組みを使って修正すればよいですね。
つまり、
 ハザードが点滅中の状態
    = 変数X右が“ON”で、かつ、変数X左も“ON”
 ウィンカーが点滅中の状態
    = (変数X右が“ON”なら変数X左は“OFF”、
         もしくは、
       変数X左が“ON”なら変数X右は“OFF”)
ということです。

ここで、着目してほしいのは、「ソフトウェアでは状態を変数の値の組合せで認識している」ということです。「状態は、前提Pのことで、前提Pとはソフトウェアで言えば“状態変数の値の組合せ”」という意味が伝わりましたでしょうか。


≡ 終わりに

今回は、状態遷移テストの基礎についてでした。

次回は「状態遷移テスト」の実践編として、「ステート・マシン図」からテストを作る方法について書きたいと思います。

この記事が気に入ったらサポートをしてみませんか?