3 方法論からモダンテスト技法へ
この資料はテスト技法セミナーのスライドに関する補助資料です.目次は右側に表示されます.
概要
プログラムの網羅度
モダン技法:テストファースト
セキュリティ問題と技法
以下に,見出しレベルを 1段深く(→ すべて ## → ###) にして再表示します. 文章中の読点”,” 句点”.“も維持しています.
3.1 デシジョンテーブル
- デシジョンテーブルの概要
デシジョンテーブルは,入力条件とそれに対応する処理や動作を表形式で整理する手法で,複雑な分岐ロジックを明確に表現できる.条件,条件の組合せ,それに対応するアクションを表にまとめることで,抜け漏れのない仕様定義やテスト設計が可能になる.
デシジョンテーブルの歴史
1960年代:商用分野で普及
デシジョンテーブルは1960年代のビジネスデータ処理で広く普及した.当時の COBOL などの業務アプリケーションでは条件分岐が複雑化しやすいため,仕様を明確にするための手法として注目された.IBM などの企業がドキュメント手法として推進した.
1970–1980年代:ソフトウェア工学で体系化
ソフトウェア設計手法の標準化が進む過程で,デシジョンテーブルは要求分析,仕様化,テスト設計における「分岐網羅の整理手法」として位置付けられた.構造化設計(Structured Analysis)の一部として標準的に扱われた.
1990年代以降:規格や品質標準に導入
組込みやミッションクリティカル領域で注目され,後述の ISO 規格やテスト標準などで活用される.
関連規格と標準
ISO/IEC/IEEE 29148(要求工学)
要求仕様の記述方法として,条件とアクションの整理にデシジョンテーブルが推奨されている.曖昧な仕様を排除する目的で利用される.
ISO/IEC/IEEE 29119(ソフトウェアテスト)
テスト設計技法として,
- デシジョンテーブルテスト
- 組合せテスト が明記されている.特に,条件の組合せの抜け漏れを防ぐためのテスト設計法として扱われる.
DO-178C(航空ソフトウェア)
ロジックが複雑な部分への要求として,条件組合せの正確性や網羅性を担保するためにデシジョンテーブルが利用されることが多い.
デシジョンテーブルの構造
条件(Condition)
入力要素や分岐に関わる要因. 例:ログイン時の「ID が正しいか」「パスワードが正しいか」など.
条件項目(Condition Alternatives)
条件に対して可能な値(通常は Yes/No,True/False).
アクション(Action)
条件が満たされたときに実行する処理.
規則(Rule)
条件の組合せとそれに対応するアクションのペア. 典型的なデシジョンテーブル形式:
| 条件 | ルール1 | ルール2 | ルール3 | … |
|---|---|---|---|---|
| 条件A | T | T | F | … |
| 条件B | T | F | T | … |
| アクションX | ✔ | |||
| アクションY | ✔ | ✔ |
デシジョンテーブルの作り方
1. 条件を列挙する
すべての分岐に関わる条件を抽出する. 例:ID 正しい,パスワード正しい,アカウントロック状態など.
2. 条件の組合せを列挙する
条件が n 個ある場合,組合せは最大で 2ⁿ 通りになる. ただし不要な組合せは縮約できる.
3. 各ルールに対してアクションを決める
例:ログイン成功,ログイン失敗,ロック中など.
4. 矛盾や抜け漏れを確認する
ルールが過不足なく定義されているかチェックする. この段階で仕様の曖昧さを発見できることが多い.
テスト設計での応用
デシジョンテーブルテスト(決定表ベーステスト)
ISO 29119 で定義されているテスト設計手法. 条件の組合せに基づきテストケースを抽出する.
特徴
- 条件が複雑なロジックに最適
- 仕様の抜け漏れ(未定義条件)を発見しやすい
- 組合せを縮約することで少ないテストで高い網羅性を得られる
- 判定条件が膨らむ組込みソフト,金融系,産業制御で広く利用される
例:ログイン判定のテストケース抽出
| 条件 | ルール1 | ルール2 | ルール3 |
|---|---|---|---|
| ID 正しい | T | T | F |
| PW 正しい | T | F | T |
| アクション | 成功 | 失敗 | 失敗 |
ここからテストケースは:
- 正しいID+正しいPW → 成功
- 正しいID+誤ったPW → 失敗
- 誤ったID+正しいPW → 失敗
と抽出できる.
デシジョンテーブルのメリット
可読性と正確性の向上
仕様漏れや条件の矛盾を早期に発見できる.
テスト網羅性の向上
複雑な条件の十分網羅を支援する.
複数チームでの認識共有
表形式なので,開発者,テスター,顧客が同じ理解を持ちやすい.
まとめ
デシジョンテーブルは1960年代のビジネス用途を起源とし,現在では ISO/IEEE 標準でも正式に採用される重要な仕様記述・テスト設計手法になっている.特に,分岐の多い組込みソフト,金融系ロジック,安全性要求の強い領域で高い効果を発揮する.
デシジョンテーブルのサンプル(基本編:ログイン判定)
条件説明
- C1:ユーザIDが正しい
- C2:パスワードが正しい
- C3:アカウントがロックされていない
アクション
- A1:ログイン成功
- A2:エラーメッセージ表示
- A3:ロック中メッセージ表示
デシジョンテーブル(完全展開 2³=8 通り)
| 条件 / ルール | R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 |
|---|---|---|---|---|---|---|---|---|
| C1:ID 正しい | T | T | T | T | F | F | F | F |
| C2:PW 正しい | T | T | F | F | T | T | F | F |
| C3:ロックなし | T | F | T | F | T | F | T | F |
| アクション | ||||||||
| A1:成功 | ✔ | |||||||
| A2:エラー表示 | ✔ | ✔ | ✔ | ✔ | ||||
| A3:ロック中 | ✔ | ✔ | ✔ |
テストケース抽出
- TC1(R1):ID 正,PW 正,ロックなし → 成功
- TC2(R2):ID 正,PW 正,ロック中 → エラー
- TC3(R3):ID 正,PW 誤,ロックなし → エラー
- TC4(R4):ID 正,PW 誤,ロック中 → ロック中
- TC5(R5):ID 誤,PW 正,ロックなし → エラー
- TC6(R6):ID 誤,PW 正,ロック中 → ロック中
- TC7(R7):ID 誤,PW 誤,ロックなし → エラー
- TC8(R8):ID 誤,PW 誤,ロック中 → ロック中
デシジョンテーブルのサンプル(応用編:組込みソフト/安全装置判定)
想定するシステム
ECU が「危険判定処理」を行い,条件に応じて警報や装置停止を行う例. 安全要求レベル(ASIL)要件を含む.
条件
- C1:センサ値が閾値以上
- C2:センサ異常(故障)検知
- C3:ASIL 高レベルモード(安全強化)
- C4:ドライバ操作で「緊急停止」ボタン押下
アクション
- A1:警報ON
- A2:装置を停止
- A3:ログ記録
- A4:フェールセーフ動作へ遷移
デシジョンテーブル(縮約後)
| 条件 / ルール | R1 | R2 | R3 | R4 | R5 | R6 |
|---|---|---|---|---|---|---|
| C1:閾値超え | T | T | F | F | F | * |
| C2:センサ異常 | F | T | T | F | F | T |
| C3:ASIL 高 | * | T | * | * | F | * |
| C4:緊急停止押下 | F | F | F | T | T | F |
| アクション | ||||||
| A1:警報ON | ✔ | ✔ | ✔ | |||
| A2:装置停止 | ✔ | ✔ | ✔ | ✔ | ✔ | |
| A3:ログ記録 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| A4:フェールセーフ | ✔ | ✔ | ✔ |
(*:条件が結果に影響しないため “don’t care” による縮約)
説明
- R1:閾値超え+異常なし → 警報とログ
- R2:閾値超え+センサ異常+ASIL高 → フェールセーフ含む強制停止
- R3:センサ異常(閾値は不問) → 停止+フェールセーフ
- R4:緊急停止押下 → 即停止
- R5:閾値以下+緊急停止 → 停止&ログ
- R6:センサ異常 → 停止+フェールセーフ
テストケース例
- TC1(R1):閾値超え,異常なし,ASIL任意,停止ボタンなし → 警報+ログ
- TC2(R2):閾値超え,異常あり,ASIL高,停止ボタンなし → 停止+フェールセーフ
- TC3(R3):閾値以下 or 超え,異常あり → 停止+フェールセーフ
- TC4(R4):停止ボタン押下 → 停止
- TC5(R5):閾値以下+停止ボタン押下 → 停止
- TC6(R6):センサ異常(閾値不問) → フェールセーフ
このサンプルが役立つ用途
- 組込みソフトの仕様レビュー
- ISO 29119 のデシジョンテーブルテスト作成
- 安全要求(ISO 26262,IEC61508)でのロジックの明確化
- 仕様の抜け漏れ検出
- テストケースの自動生成やモデルベーステスト
3.2 プログラムの網羅度
プログラムの品質評価では,テストがどの程度コードを実行したかを示す「網羅度」が重要となる.網羅度は,制御構造や経路をどれだけ試験できたかを測る指標であり,テスト手法や要求品質に応じて複数のレベルが存在する.ここでは,代表的な網羅度として,命令網羅,分岐網羅,条件網羅,MC/DC,そして完全なパス網羅の一種である prime path coverage を中心に整理する.
命令網羅(Statement Coverage)
命令網羅は,プログラム中の各命令(ステートメント)が少なくとも1回実行されたかを測定する.
- 最も基本的な網羅指標で,計測しやすい.
- ただし,制御フローの分岐や状態遷移の複雑さを十分に捉えられない.
- 高い命令網羅率でも重大な欠陥が残る可能性がある.
分岐網羅(Branch Coverage / Decision Coverage)
分岐網羅は,制御フロー上の各分岐(if, while, for など)について, 真となる経路と偽となる経路の両方を実行したかを測る.
- 「アーク網羅」と呼ぶこともある.
- 命令網羅より強力で,基本的な制御フローの確認が可能.
- ただし複雑な条件式の内部評価までは保証できない.
例:if (A && B) がある場合
- 分岐網羅は if が「true」と「false」になればよい
- ただし A と B のどちらが false で落ちたかまでは保証しない
条件網羅(Condition Coverage)
条件網羅は,複合条件式を含む各部分条件について true と false の両方が評価されることを保証する.
- 分岐網羅より強力
- ただし部分条件の組み合わせまでは保証しない
条件/判定網羅(Condition/Decision Coverage, C/DC)
分岐網羅と条件網羅の両方を満たしたもの.
- 判定結果の全分岐+条件式内部の true/false を両方確認
- ただし条件の組み合わせの最小性までは保証しない
MC/DC(Modified Condition/Decision Coverage)
航空宇宙や自動車ソフトウェア安全基準(DO-178C, ISO 26262)で要求される高度な網羅度. MC/DC では,各部分条件が 他の条件に依存せず,判定結果に独立して影響を与えることを確認する.
- 複雑な論理式に対して,最小限のテスト数で強力な検証が可能
- 安全性クリティカルシステムで広く採用される
パス網羅(Path Coverage)
制御フローグラフ上で,可能な 全ての実行経路を実行することを目指す網羅度.
- 最も強力な網羅基準
- しかし実際には経路数が爆発的に増える(状態爆発)ため,非現実的なことが多い.
- ループがある場合は理論上無限の経路が存在し,完全網羅は不可能.
Prime Path Coverage(主要な経路の網羅)
Path Coverage が現実的ではないため,実務的な妥協として導入されるのが prime path coverage(主要経路網羅)である. Prime path とは, 他の経路に完全に含まれない「最大の単純経路」を指す.
- 無限に多い経路の代わりに,有限個の重要経路のみを網羅
- 分岐網羅より強力で,Path Coverage の近似として使われる
- 最近のツール(例:gcov の拡張パッチなど)で計測が進む分野
Prime Path Coverage の特徴
- ループ内の繰り返しを1回に限定しつつ,重要な制御構造を網羅
- 全経路の中で構造的に代表性が高い経路を選ぶ
- 経路数は有限かつ現実的な範囲に収まる
- 高品質だが計測は比較的複雑
分岐網羅と prime path coverage の違いのまとめ
| 観点 | 分岐網羅(アーク網羅) | Prime Path Coverage |
|---|---|---|
| 保証される範囲 | 各分岐の true/false を通過 | 最長の単純経路をすべて通過 |
| 経路数 | 比較的少ない | 分岐網羅より多いが有限 |
| 効果 | 基本的な制御構造の確認 | より複雑な制御構造も検出可能 |
| 欠陥検出能力 | 中程度 | 高い |
| 実用性 | 高い | 中程度(工数増) |
| 安全性基準での扱い | 必要に応じて | 高度安全基準で議論増加 |
網羅度のまとめ
プログラム網羅度の指標は,
- 実装の安全性
- 設計の複雑さ
- テストコスト
- 証明の容易性
のバランスによって使い分けられる. 分岐網羅は広く利用される基本的な指標であり,prime path coverage は高信頼システムや研究分野で注目される強力な基準である.必要な品質レベルに応じて,段階的に強い網羅基準を選ぶのが実務的である.
3.3 仕様 割引問題
ある施設の入場料金に対する割引を定めた仕様
- 水曜日なら,正規の90%とする.
- 60 歳以上なら,正規の60%とする.
- 施設の記念日なら,正規の80%とする.
- 15 時以降の入場なら正規の70%とする.
- 12 歳以下なら正規の40%とする.
- 条件が重複する場合には,割引の大きい方を選択する.
- 例:水曜日で12歳以下
- 施設の記念日で15時以降
入力をまとめると
int waribiki(int age,int dayofweek,int memorialday,int intime)
- age : 正の整数
- dayofweek : 1から7の整数 水曜は3
- memorialday : 1かそれ以外 1は記念日
- intime : 入場時間 範囲は10-20
出力をまとめると
int waribiki()
- 結果はint型で値は
waribikiの結果:
40 : 正規料金の40%
60 : 正規料金の60%
70 : 正規料金の70%
80 : 正規料金の80%
90 : 正規料金の90%
100 : 正規料金
3.4 派生仕様 割引問題の仕様変更
仕様変更: 例題を使って考える
- 先の割引問題を次のように拡張する
- 割引をいろいろ追加した(☆印).
- ☆3 歳以下の場合には無料とする.(正規の0%)
- 水曜日なら,正規の90%とする.
- 60 歳以上なら,正規の60%とする.
- ☆女性の場合,50 歳以上なら正規の65%とする.
- 施設の記念日なら,正規の80%とする.
- ☆施設の地域住民なら,正規の50%とする.
- 15 時以降の入場なら正規の70%とする.
- 12 歳以下なら正規の40%とする.
- 条件が重複する場合には,割引の大きい方を選択する.
関数レベルの仕様
int waribiki(int sex,int age,int dayofweek,int citizen,int month,int memorialday,int intime)
/*
sex: 性別 男==1 女==2 不明=それ以外
age:年齢
dayofweek:曜日(月==1 日==7)
citizen:住居 地域住民=1
month:月(1-12)<上の仕様では未使用>
memorialday: 記念日=1 それ以外は記念日ではない
intime:入場時間(0-24) 有効な範囲は10-20
*/
- 引数にmonthがあるが,将来の拡張用として設定.
- しかし,値を与えないと引数エラーになる
結果の仕様化
- 仕様から,0,40,50,60,65,70,80,90,100
- 結果は9種類(改造前6)
- YAML定義なら
waribikiの結果:
0 : 無料 ☆
40 : 正規料金の40%
50 : 正規料金の50% ☆
60 : 正規料金の60%
65 : 正規料金の65% ☆
70 : 正規料金の70%
80 : 正規料金の80%
90 : 正規料金の90%
100 : 正規料金
入力(原因)の仕様化
- 追加になったのは
- sex: 性別 男==1 女==2 不明=それ以外?
- citizen:住居 地域住民=1 それ以外は1以外
- month:月(1-12)<今回の改修仕様では未使用>