ブラックボックステストとホワイトボックステストは、どちらか一方を選ぶものではなく、検出できる欠陥の種類が異なるため併用するものです。両者を「ユーザー視点か開発者視点か」とだけ説明した記事は多いものの、実務では、対象のリスクに応じた技法と網羅基準に加え、期待結果の確かめ方やテストの保守負担も判断します。本記事では JSTQB の Foundation Level シラバス Version 2023V4.0.J02(2023年4月12日)の定義を出発点に、両者の技法とカバレッジ基準を整理し、命令網羅100%でも欠陥が残ることを実際に計測したログで示します。
まとめ
結論として、テスト対象の仕様が確定していればブラックボックステスト技法でテストケースを作り、そのうえでホワイトボックステストのカバレッジ計測を「テストの十分性を客観的に確かめる物差し」として重ねるのが基本形です。ホワイトボックステストは、ブラックボックステストを置き換えるものではありません。
| 観点 | ブラックボックステスト | ホワイトボックステスト |
|---|---|---|
| JSTQBでの別名 | 仕様ベース技法 | 構造ベース技法 |
| 根拠にする情報 | 仕様上の振る舞い | 内部構造と処理 |
| 作成できる時期 | 対象の振る舞いを定義した段階 | 対象の設計または実装が整った段階 |
| 実装変更への耐性 | 振る舞いが同じなら再利用可 | 構造変更に応じて見直し |
| 代表技法 | 同値分割法/境界値分析/デシジョンテーブル/状態遷移 | ステートメントテスト/ブランチテスト |
| カバレッジの単位 | パーティション・境界値・列・遷移 | 実行可能ステートメント・ブランチ |
| 苦手な欠陥 | 仕様に書かれていない内部の分岐漏れ | 要件そのものが未実装である欠落 |
ブラックボックステストとホワイトボックステストの違い
JSTQBシラバスの定義と、呼び名が2通りある理由
JSTQB Foundation Level シラバス V4.0 は、テスト技法をブラックボックス・ホワイトボックス・経験ベースの3つに分類しています。ブラックボックステスト技法については「ブラックボックステスト技法(仕様ベース技法とも呼ばれる)は、テスト対象の内部構造を参照することなく、仕様上の振る舞いの分析に基づくものである」と定義しています。ホワイトボックステスト技法は「テスト対象の内部構造や処理の分析に基づくものである」とし、構造ベース技法とも呼ばれると併記しています(出典:JSTQB Foundation Level シラバス Version 2023V4.0.J02 4.1節)。
「仕様ベース」「構造ベース」という別名は言い換えではなく、何を根拠にテストケースを導出したかを指しています。仕様書からケースを起こしたなら仕様ベース、ソースコードの分岐からケースを起こしたなら構造ベースです。この区別が効くのは、テスト設計の妥当性をレビューするときです。「その入力値はどこから来たのか」を問えば、仕様に紐づかない思いつきのケースを切り分けられます。
テストケースが実装変更に耐えるかどうかという差
実務上いちばん効いてくる違いは、作成時期と寿命です。シラバスはブラックボックステストについて「結果的に実装が変わったとしても、求められる振る舞いが同じであれば、テストケースは依然として有用である」と述べています。一方でホワイトボックステストは「テストケースはソフトウェアの設計方法に依存するため、テスト対象の設計や実装が終わってからでないと作成できない」と明記されています。
内部の呼び出し順序や非公開メソッドに強く依存するテストは、リファクタリングで修正が必要になることがあります。ただし、内部構造から入力を選び、公開された振る舞いを検証するテストまで必ず失敗するわけではありません。仕様書に例外条件が書かれていない場合は、要件を確認し、内部構造の分析や経験ベースの技法も使って入力条件を特定します。両者の使い分けは思想の問題ではなく、テストケースの寿命とコストの問題です。
ブラックボックステストの4技法とカバレッジの数え方
JSTQB V4.0 が Foundation Level で扱うブラックボックステスト技法は、同値分割法・境界値分析・デシジョンテーブルテスト・状態遷移テストの4つです。いずれも「何をカバレッジアイテムとして数えるか」がセットで決まっている点が重要で、これを曖昧にしたまま「網羅した」と主張するテスト計画がもっとも危険です。
同値分割法の分割対象と網羅基準
同値分割法は、同じ扱いを受けるはずのデータをパーティションに分け、各パーティションから1件ずつテストする技法です。シラバスは前提を「同値パーティションから1つの値をテストするテストケースが欠陥を検出した場合、この欠陥は同じパーティションから他の値をテストするテストケースでも検出されるはずだ」と説明し、そのうえで「各パーティションに対して1つのテストがあれば十分である」としています。
設計時に見落としやすいのは、パーティションを作る対象が入力値に限らない点です。シラバスは「入力、出力、構成アイテム、内部値、時間関連の値、インターフェースパラメーターなど、テスト対象に関連するあらゆるデータ要素について識別できる」と列挙しています。また、パーティションは重複してはならず、空でない集合でなければならないという制約があります。同じ分割対象の同値パーティションが重複している場合は、区分の境界や分類条件を見直します。
境界値分析(2値BVAと3値BVA)
境界値分析は同値分割の境界に着目する技法で、順序性のあるパーティションにのみ使えます。ここで多くの解説記事が触れないのが、境界1つあたり何点取るかに2つの流儀があることです。2値BVAは境界値とその隣接パーティション側の最も近い値の2点、3値BVAは境界値と両隣の3点をカバレッジアイテムとします。
この差は机上の区別ではありません。シラバスは具体例を挙げ、「if(x≦10)…」という判定を誤って「if(x=10)…」と実装した場合、2値BVAで導出される x=10 と x=11 では欠陥を検出できず、3値BVAで加わる x=9 が検出しうると説明しています。境界のずれではなく判定演算子そのものを間違えた欠陥は、2点では素通りするということです。金額の閾値や年齢区分など、演算子の取り違えが即座に金銭影響になる箇所では3値BVAを選ぶ判断材料になります。
デシジョンテーブルテストの網羅単位とルール削減
デシジョンテーブルテストは、条件の組み合わせが異なる結果をもたらす仕様を検証する技法です。カバレッジアイテムは「実行可能な条件の組み合わせを含む列」で、100%にするには全列を通す必要があります。強みは網羅そのものより副作用のほうにあり、シラバスは「要件の相違点や矛盾を発見するのにも役立つ」と述べています。表を埋める過程で、仕様書に書かれていない組み合わせが空欄として可視化されるためです。
弱点は素直に指数関数的なコストです。条件が増えると判定ルールが急増するため、実行不可能な組み合わせの列を削除し、結果に影響しない条件を統合して最小化します。さらに削減する場合は、リスクに応じて直交表やペアワイズ法などを検討します。ただし、ペアワイズ法では3条件以上の組み合わせに依存する欠陥を見逃す可能性があり、重要な業務ルールは別途確認します。表の作り方と削減の実務はテストマトリクスとは?作り方・サンプル表・観点とパターン削減で扱っています。
状態遷移テストの3つの網羅基準
状態遷移テストは、状態と遷移でシステムの振る舞いをモデル化し、遷移を「イベント[ガード条件]/アクション」の形でラベル付けします。カバレッジ基準が3段階ある点が実務上の判断ポイントです。全状態カバレッジは状態を、有効遷移カバレッジ(0スイッチカバレッジ)は有効な遷移を、全遷移カバレッジは状態表に現れる無効な遷移も含めてカバレッジアイテムとします。
強さの順序は明確で、全状態カバレッジは有効遷移カバレッジより弱く、有効遷移カバレッジを完全に達成すれば全状態カバレッジも保証されます。実務で最も使われるのは有効遷移カバレッジですが、シラバスは全遷移カバレッジについて「ミッションクリティカルおよびセーフティクリティカルソフトウェアの最低要件とすべきである」と踏み込んで書いています。無効な遷移を試すテストは、1テストケースにつき無効遷移を1つだけ扱うのが原則です。複数を同時に試すと、ある欠陥が別の欠陥の検出を妨げる欠陥のマスキングが起きます。
ホワイトボックステストのカバレッジ基準
ステートメントカバレッジとブランチカバレッジ
JSTQB V4.0 が Foundation Level で扱うホワイトボックステスト技法は、ステートメントテストとブランチテストの2つだけです。ステートメントカバレッジは実行可能ステートメントを、ブランチカバレッジは制御フローグラフのノード間の制御の遷移をカバレッジアイテムとします。ブランチには条件分岐だけでなく無条件の遷移も含まれます。
両者の関係は包含関係にあり、シラバスは「ブランチカバレッジはステートメントカバレッジを包含する。つまり、ブランチカバレッジ100%を達成した一連のテストケースは、100%のステートメントカバレッジも達成する(しかし、その逆は成立しない)」と明記しています。逆が成立しないという但し書きが、次の章で実測する内容そのものです。
さらにシラバスは、ステートメントカバレッジ100%の限界として「判定ロジックをすべてテストしていることは確認できない」こと、そして分母が0のときだけ失敗するゼロ除算のようなデータ依存の欠陥は検出されない可能性があることを挙げています。カバレッジ率は「テストが足りている証明」ではなく「足りていない箇所の指摘」として読む指標です。同じ性質の指標であるバグ密度やテスト密度の読み方はバグ密度・テスト密度の目安|IPA基準値と計算式・ゾーン分析で整理しています。
MC/DCとDO-178Cが要求する水準
シラバスは、Foundation Level の範囲外として「一部のセーフティクリティカル、ミッションクリティカル、または高い完全性が求められる環境で使用する、より徹底したコードカバレッジを実現するためのより厳密な技法が存在する」と述べるにとどめています。その代表が MC/DC(改良条件判定カバレッジ)です。
MC/DC の定義は、NASA ラングレー研究センターの Hayhurst らによる解説論文が DO-178B の規定を引用しています。すなわち「Every point of entry and exit in the program has been invoked at least once, every condition in a decision in the program has taken all possible outcomes at least once, every decision in the program has taken all possible outcomes at least once, and each condition in a decision has been shown to independently affect that decision’s outcome」の4条件です(出典:NASA「A Practical Approach to Modified Condition/Decision Coverage」)。判定の中の各条件が、他の条件を固定したまま単独で判定結果を左右できることを示す必要があります。
同論文は、DO-178B がレベルA、つまり異常動作が壊滅的な結果を招きうるソフトウェアに対して MC/DC の達成を要求すると説明しています。この要求はソフトウェアレベルごとに段階化されており、FAA の技術報告 DOT/FAA/TC-16/4 が引用する Table A-7 の目標には「A-7.5 Test coverage of software structure (modified condition/decision) is achieved.」「A-7.6 Test coverage of software structure (decision coverage) is achieved.」「A-7.7 Test coverage of software structure (statement coverage) is achieved.」が並びます(出典:FAA DOT/FAA/TC-16/4)。ステートメント、デシジョン、MC/DC の3段が別々の目標として定義され、適用範囲がレベルによって変わる構造です。
この段階構造は航空分野だけの決めごとではありません。JSTQB シラバスが技法の参照先として挙げる ISO/IEC/IEEE 29119-4:2021(第2版・2021年10月28日発行)も、構造ベースドテスト設計技法として Statement testing、Branch testing、Decision testing、Branch condition testing、Branch condition combination testing、Modified condition/decision coverage testing を順に規定しています。実務で読み取るべきは、航空機の話だから無関係だということではなく、分岐網羅100%の上にもう数段の基準が標準として実在するという事実です。決済や医療機器の判定ロジックで分岐網羅を満たしたとき、条件の独立影響まで見るべきかを検討する余地があります。
coverage.pyによる命令網羅100%と欠陥残存の実測
「ステートメントカバレッジ100%でもブランチは通っていない可能性がある」という記述は、実際に計測すると数行のコードで再現できます。ここでは Python の coverage.py 7.10.7 を使い、同じテストに対して命令網羅と分岐網羅を続けて計測しました。題材は送料計算です。
def shipping_fee(weight, is_member):
fee = 800
if weight > 10:
fee = 1500
if is_member:
fee = fee - 300
return fee
仕様は「10kg超は1500円、それ以外は800円。会員は300円引き。ただし会員でも下限は600円」とします。テストは1本だけ用意しました。
import unittest
from shipping import shipping_fee
class TestShippingFee(unittest.TestCase):
def test_heavy_member(self):
self.assertEqual(shipping_fee(12, True), 1200)
if __name__ == "__main__":
unittest.main()
先の関数をshipping.py、テストをtest_shipping.pyとして同じディレクトリに保存します。Python環境に「python3 -m pip install coverage==7.10.7」で導入したうえで、まず分岐オプションなしで計測します。
$ python3 -m coverage run test_shipping.py
$ python3 -m coverage report -m shipping.py
Name Stmts Miss Cover Missing
-------------------------------------------
shipping.py 7 0 100%
-------------------------------------------
TOTAL 7 0 100%
ステートメントカバレッジは100%、未実行ステートメントは0件です。この数字だけを品質報告に載せれば「網羅済み」に見えます。同じテストのまま、分岐カバレッジを有効にして計測し直します。
$ python3 -m coverage run --branch test_shipping.py
$ python3 -m coverage report -m shipping.py
Name Stmts Miss Branch BrPart Cover Missing
---------------------------------------------------------
shipping.py 7 0 4 2 82% 3->5, 5->7
---------------------------------------------------------
TOTAL 7 0 4 2 82%
BrPart の2は、分岐先の一部が未実行である分岐元が2件あることを示します。Missing 欄の 3->5 と 5->7 は、3行目の判定が偽のとき5行目へ進む経路と、5行目の判定が偽のとき7行目へ進む経路が一度も通っていないという意味です。つまり「軽い荷物」と「非会員」の経路が未検証でした。
ここで Cover 欄の82%を「分岐網羅率が82%」と読むのは誤りです。coverage.py の公式ドキュメントは算出方法を「The coverage percentage for a file is the actual executions divided by the execution opportunities. Each line in the file is an execution opportunity, as is each branch destination.」と定義しており、行と分岐先を合算した達成率です。この例では7行と分岐先4件の計11機会に対して9件が実行されたため82%になります。分岐単独で見れば4件中2件、つまり50%です。レポートの数字をそのまま分岐網羅率として品質報告に転記すると、実態より良く見えます。
そして、この未実行分岐のうえに仕様違反が潜んでいます。会員かつ10kg以下の経路を実行すると、次の値が返ります。
$ python3 -c "from shipping import shipping_fee; print(shipping_fee(5, True))"
500
下限600円という仕様に反して500円が返っています。ステートメントカバレッジ100%の報告書は、この欠陥を一度も指摘しませんでした。
分岐網羅100%にしても欠陥が残る
では分岐を埋めれば足りるのかというと、そうではありません。未実行だった2つの経路を通すテストを1本追加します。
def test_light_nonmember(self):
self.assertEqual(shipping_fee(5, False), 800)
この2本で計測すると、未実行の分岐は消えます。
$ python3 -m coverage run --branch test_shipping2.py
$ python3 -m coverage report -m shipping.py
Name Stmts Miss Branch BrPart Cover Missing
---------------------------------------------------------
shipping.py 7 0 4 0 100%
---------------------------------------------------------
TOTAL 7 0 4 0 100%
BrPart は0、Cover は100%です。それでも shipping_fee(5, True) は500を返したままで、下限600円の違反は残っています。追加したテストが通ったのは「軽い荷物かつ非会員」の組み合わせであり、欠陥が現れる「軽い荷物かつ会員」の組み合わせは、分岐を全て通してもなお検証されていないからです。JSTQB シラバスもこの限界を「テストケースでブランチを通過しても、すべてのケースで欠陥が検出されるわけではない」と明記しています。
この3つのログから導ける実務上の判断は、カバレッジ率は達成度ではなく未検証箇所の指摘として読む、というものです。命令網羅の数値だけを見れば未実行の経路を見落とし、分岐網羅100%を達成しても仕様に基づく期待値の検証が伴わなければ欠陥は残ります。静的解析と動的テストの違いとは|検出できるバグ・代表ツール・使い分けを比較で扱っている静的解析は、到達不能コードなどの検出に使えます。ただし、この例の経路は到達可能であり、今回のテストが通らなかった経路の特定には実行記録との照合が必要です。
テストレベルとの対応とグレーボックステスト
「単体はホワイト、システムはブラック」という対応づけの誤り
テスト技法とテストレベルを1対1で結びつける説明が広く流通していますが、JSTQB V4.0 はその対応を採っていません。シラバスはホワイトボックステスト技法について「より高いテストレベル(例えば、APIテスト)で使用するホワイトボックステスト技法」の存在に触れ、コードに関係ないカバレッジとしてニューラルネットワークテストにおけるニューロンカバレッジまで例示しています。
例えば、単体テストでも仕様に基づく同値分割でケースを導出すれば、ブラックボックステスト技法を使ったことになります。逆に、結合レベルで内部の呼び出し経路を根拠にケースを作れば構造ベースです。判断の基準はテスト工程の名前ではなく、テストケースの導出根拠が仕様か内部構造かという一点です。テストレベルという区分自体の限界については単体テストと結合テストはもう古い?Google流「テストサイズ」とは(Small/Medium/Large)で扱っています。
グレーボックステストの位置づけと弱点
グレーボックステストは、内部構造の情報を部分的に持ったうえで外部から操作するアプローチを指します。データベースのスキーマやAPIの内部仕様を把握したテスターが、画面操作で境界を突くようなケースが該当します。JSTQB Foundation Level シラバス V4.0 の技法分類には登場しない用語です。ただし認定資格全般で扱われないわけではなく、ISTQB の Security Test Engineer シラバス v1.0 は2.1.1節でグレーボックスセキュリティテストを扱い、NIST の定義を引いて「a test methodology that assumes some knowledge of the internal structure and implementation detail of the assessment object」としています。Foundation Level のテスト技法分類には無く、セキュリティテストの文脈では正式に定義がある、という位置づけです。
運用上は2つの点に注意が必要です。ひとつは、参照した内部情報とケースの導出根拠を記録しないと、再現やレビューが難しくなることです。もうひとつは、グレーボックスという呼称だけではカバレッジの分母が決まらないことです。要件、状態遷移、利用可能な内部構造などから測定対象を定義します。構造カバレッジを測るには計測対象のコードにフックが要り、それを入れるならホワイトボックステストとして扱ったほうが数値が残ります。グレーボックスという呼称が表すのは、内部情報を部分的に利用するというアクセス条件です。ケースを仕様から導くか、内部構造から導くか、経験から導くかは、呼称とは別に整理する必要があります。
「ホワイトボックステストは意味がない」と言われる理由
ホワイトボックステストへの批判を考える際は、カバレッジの達成と期待結果の検証を分けて考える必要があります。この批判には正しい部分があり、それを認めたうえで線を引くべきです。
正しいのは「カバレッジ率の追求それ自体は品質を上げない」という点です。分岐を通すだけのテストは、アサーションが弱ければ何も検証していません。テストケース数とカバレッジ率だけをノルマにすると、期待結果の検証が弱いテストまで増やしてしまうおそれがあります。さらに JSTQB シラバスは構造上の限界を明示しており、「ソフトウェアが1つまたは複数の要件を実装していない場合、ホワイトボックステストでは、結果として生じる欠落を欠陥として検出できない可能性がある」としています。存在しないコードは、どれだけ網羅しても現れません。
それでもホワイトボックステストが要る理由は2つです。第一に、シラバスが述べるとおり「ソフトウェアの仕様が曖昧であったり、古かったり、不完全であったりしても、欠陥の検出を容易にする」点です。仕様書が現物に追いついていないレガシーシステムでは、内部構造も調査の手掛かりになります。ただし、現行コードにも欠陥はあり得るため、業務要件や利用者への確認と照合します。第二に、測定の代替手段がないことです。シラバスは「ブラックボックステストだけを実施しても、実際のコードカバレッジを測定することはできない」と言い切っています。前章の実測がまさにこれで、テストが通ったという結果からは未検証の経路の存在を知ることができませんでした。
したがって実務上の推奨は明確です。テストケースの設計はブラックボックステスト技法で行い、内部構造に基づくホワイトボックスのテスト設計も併用してください。カバレッジ計測で見つかった未実行分岐に加え、要件の未実装や条件の組み合わせの不足も確認してテストを追加します。カバレッジ率だけを品質の合否基準にするのは避けてください。リスクや適用規格に応じて達成目標を設定し、期待結果の検証、未解決欠陥、残存リスクと組み合わせて終了を判断します。
よくある質問
ブラックボックステストにおけるテストケースの設計方法として適切なものはどれですか?
仕様に基づいてテストケースを導出する技法が該当します。JSTQB Foundation Level シラバス V4.0 が挙げるのは、同値分割法・境界値分析・デシジョンテーブルテスト・状態遷移テストの4つです。ソースコードの分岐や命令を根拠に入力値を決める方法は、ブラックボックステストではなくホワイトボックステスト技法にあたります。なお情報処理技術者試験では用語が一部異なります。IPA の基本情報技術者試験シラバス Ver.9.2(2026年1月8日掲載)は「テストで用いられるブラックボックス法,ホワイトボックス法のテストデータの作成方法を理解する」とし、用語例に命令網羅、条件網羅、判定条件網羅、複数条件網羅、限界値分析法、同値分析法を挙げています。JSTQB の「境界値分析」「同値分割法」が、試験では「限界値分析法」「同値分析法」として問われる点に注意してください。
ブラックボックステストで検出できない不具合は何ですか?
外部から観測できる振る舞いに影響しない内部の欠陥は、入出力の確認だけでは検出できません。ただし、本記事の送料の下限違反は仕様に基づくブラックボックステストでも検出でき、この分類には当たりません。本記事の実測例では、仕様として書かれた振る舞いを満たすテストが通ったにもかかわらず、未実行の分岐に下限600円の仕様違反が残っていました。性能要件は、応答時間や処理件数を外部から測るブラックボックステストでも検証できます。メモリリークは、長時間運転とメモリ使用量の監視など、機能の出力確認とは別の観測を組み合わせて調べます。
ホワイトボックステストの種類にはどのようなものがありますか?
JSTQB Foundation Level シラバス V4.0 が扱うのは、ステートメントテストとブランチテストの2つです。この範囲外に、条件カバレッジや MC/DC といったより厳密な基準、およびデータフローテストがあります。MC/DC は DO-178C のレベルAソフトウェアで要求される水準です。
命令網羅と分岐網羅はどちらを目標にすべきですか?
分岐網羅です。ブランチカバレッジ100%を達成したテストケースはステートメントカバレッジ100%も達成しますが、逆は成立しません。本記事の計測では、命令網羅100%に対して分岐単独の網羅率は4件中2件の50%で、未実行の経路に欠陥が残っていました(レポートに出る82%は行と分岐先を合算した値です)。ただし分岐網羅100%も十分条件ではなく、同じ例ではテストを追加して100%にしても欠陥は残りました。達成目標はリスクや適用規格に応じて定め、数値だけで合否を判断せず、未実行分岐と仕様上の検証不足の両方を確認してください。
境界値分析は境界の前後で何点取ればよいですか?
2値BVAなら境界値と隣接値の2点、3値BVAなら境界値とその両隣の3点です。3値BVAのほうが厳密で、判定演算子の取り違え、たとえば x≦10 とすべき箇所を x=10 と実装した欠陥を検出できます。金額や年齢の閾値のように演算子の誤りが直接損失につながる箇所では3値BVAを選ぶ判断があります。