『ソフトウェアテスト技法 練習帳』のPart3「状態遷移テスト」の章で、カバレッジ基準の表現が2種類あることに気が付きました。
「1スイッチカバレッジ」と、「C1カバレッジ(遷移網羅)」という表現です。
「C1カバレッジ」という表現はコードカバレッジの文脈でしか見たことがなく、状態遷移テストにおいてあたるのは初めてだったのでつぶやいてみたところ、秋山さんからコメントいただきました。
29119-4では、状態、0スイッチ、全パス、Nスイッチが定義されていて、0スイッチは有効パスだけです。
— あきやま🐾 (@akiyama924) 2020年5月6日
C1については、どこの定義を見たら良いか分かりませんが、『知識ゼロ』本あたりから、「N/Aもテストしよう」というのが広まっているように思います。
これを機に、状態遷移テストのカバレッジ基準について整理しておきましょう。
ちなみに、コードカバレッジについては以下で書いてます。
キャッツの方の連載における定義
まずは、状態遷移テストにおける「C0」について調べてみましょう。
浅く検索しただけではあまり見当たらないのですが、キャッツの塚田 雄一さんによるMONOistの連載「状態遷移表による設計手法」では、状態遷移表に基づくホワイトボックステストが解説されています。
この記事には「C0」「C1」という表現が出てくるのですが、状態遷移テストにC0・C1という網羅基準があるという話ではなく、コードカバレッジのC0・C1を、状態遷移表から簡易に導出することができるというお話です*1。
この記事では、C0は命令網羅、C1は分岐網羅のことを指しています。状態遷移表におけるアクションを「命令」と見なし、これをすべて通過するようにテストケースを導出することで、命令網羅を達成できます。
また、(後述のastah*でいう)「ignore」や「cannot happen」も含めてすべてのアクションセルをカバーするようにテストケースを導出することで、分岐網羅を達成できるという考え方です。
いずれにせよ、『練習帳』でいう「C1カバレッジ(状態網羅)」とは違うものですね。
ISO/IEC/IEEE 29119 Part4における定義
国際規格をのぞいてみましょう。
ソフトウェアテスト設計技法を扱うISO/IEC/IEEE 29119 Part4では、状態遷移テストの網羅対象として、以下の4つを扱っています。
- 状態: モデルにおけるすべての状態に到達する。
- 単一遷移(0スイッチカバレッジ): モデル内の有効な単一遷移をすべてカバーする。
- 全遷移: モデルにおける有効な遷移と無効な遷移をともにすべてカバーする。(無効な遷移とは、有効な遷移が指定されていないイベントによる遷移)
- 複数遷移(Nスイッチカバレッジ): モデルにおける連続(N+1)回の有効な遷移をカバーする。
「C1カバレッジ」はありませんが、「遷移網羅」に近いのは、「単一遷移」でしょう。
また『練習帳』では「C1カバレッジ(遷移網羅)、および、遷移しない無効トリガー動作」と表現されています。これは「全遷移」に対応すると考えてよさそうです。無効な遷移は、『練習帳』では「N/A」、後述のastah*でいう cannot happen に相当します。
astah*によるモデリング
いきなりですが、モデリングツール「astah*」で、問題3.5の状態遷移をモデリングしてみましょう。
なおastah*は「新型コロナウイルスで働き方に影響を受ける皆様へ」という形で、暫定的な無償ライセンスを提供してくださっています。粋な計らいですね。
今回はこのライセンスを使用させていただきます!
状態遷移図と状態遷移表
描いた状態遷移図は以下の通り。問題の内容は、書籍を読んでくださいね!
「超電磁バリア」→「超電磁バリア」の遷移は、あえて省いています。
ここから自動生成される*2状態遷移表は、以下の通りです。
たくさんのセルが空白のまま残っています。別の状態に遷移しない場合、以下の2つのいずれかを入力します*3。
- ignore: 当該イベントが発生しても、発生しなかったように扱う。
- たとえば、「超電磁バリア」中に「敵を発見する」*4。
- cannot happen: 当該イベントは発生しえない。
- たとえば、「停止中」に「敵を発見する」。
なお『練習帳』では、ignore は同じ状態への遷移(たとえば超電磁バリア→超電磁バリア)と扱われ、cannot happen は「N/A」と表記されています。
テストケースの導出
さてastah*では、プラグインを導入することで、状態遷移表からテストケースまで導出することができます*5。その結果が以下です。
遷移回数が「1」というのは、0スイッチカバレッジを意味します。
状態遷移表の紫色をカバーすることで、0スイッチカバレッジ = 100% を達成できます*6。
ただ上図を見てわかる通り、ここに現れるのは「有効な遷移」のみです。cannot happen セルは含まれていません。
遷移回数を2にすると、1スイッチカバレッジとなります。
状態→遷移→状態→遷移→状態 となっていることがわかります。
遷移が2つ、状態が3つなのに「1」スイッチカバレッジというのは正直いまだにしっくりきませんが。
他の網羅基準
さて、ちょっと余談。
「遷移網羅」というのは一見、もっとも基本的な網羅基準にも思えますが、実はより単純な網羅基準があります。
- イベントカバレッジ: 定義されたすべてのイベントをカバーしている。
- 状態カバレッジ: 定義されたすべての状態をカバーしている。
- アクションカバレッジ: 定義されたすべてのアクションをカバーしている。
まあそのままなのですが。
たとえば以下のテストケースがあるとしましょう。
- 状態「停止中」でイベント「スイッチを押す」を起こす
- 状態「起動中」でイベント「敵を発見する」を起こす
- 状態「超電磁バリア」でイベント「敵がいなくなってから30秒経過する」を起こす
この場合、イベント網羅は100%(3/3)ですが、「停止中」に遷移するテストケースはないので、状態網羅は67%(2/3)になってしまいます*7 。さらに、有効な遷移5つのうち3つしか実行していないので、遷移網羅は60%ですね。
また、ファンクションネットでは reachability という言葉が出てきました。指定した状態に到達できるか否かという話です。
状態遷移テストでも、開始状態と指定状態を指定した場合に可能な経路の網羅など、遷移の数とはまた違う視点のカバレッジ基準があるようです。
*1:実際のコードではないので、「モデルベースのコードカバレッジ」とでも呼べるかもしれません。
*2:astah*素晴らしいですね。
*3:詳細説明は以下。 www.changevision.co
*4:この場合、30秒タイマーがリセットされると考えると、「無視する」とするのは適切でないかもしれません。
*5:astah*素晴らしいですね。
*6:秋山さんに指摘されて気づいたのですが、状態遷移表では紫になっていない ignore も含めてパスが導出されていますね。ignore を29119でいう「無効」と考えると、astah*における「遷移回数=1」のカバレッジは、29119における無効パスも含むと考えられます。全網羅に相当・・・?
*7:ここでは「遷移後」に状態が出てきて初めて網羅されたとみなしています。29119の状態網羅の定義に visited という言葉があるというのが、その根拠です。