ユニットテストと結合テストの境界の知識マップ(知識グラフ)
ユニットテストと結合テストの境界を、判断のテストか接続のテストかという軸で整理する記事です。金額計算や状態遷移のような分岐の総当たりはユニットテストへ寄せ、フォーマット・配線・環境・時間という4つの境界はin-memoryのfakeでは意味が落ちるため結合テストへ置くべきだとします。stub・mock・fakeというテストダブルの違いを整理したうえで、mockが増えすぎる兆候は配線をユニットテストへ押し込んでいる合図であり、コア層をユニットテストで厚く、境界層を狭い結合テストで、全体層を少数のスモーク/E2Eで構成する3層構成を実務での落としどころとして示します。
ユニットテスト
分離された1責務の正しさを、外部資源を切り離して確かめるテストの層のこと。
単体テスト
結合テスト
複数コンポーネントの接続と、インフラやフレームワークを含む挙動を確かめるテストの層のこと。
統合テスト
スタブ
既存の依存関係を置き換える、コントロール可能な代役のこと。決められた値を返すために使う。
モック
テストの合否を左右するAssert操作の対象になる、呼ばれ方そのものを検証する代役のこと。
フェイク
スタブやモックを指す総称、または本物と同じ振る舞いを軽い実装で置き換えたもののこと。
フォーマットの境界
JSON/XML/CSVのシリアライズやDBのスキーマ・mapping、文字コードなど、データ形式の変換に関わる境界のこと。
配線の境界
DI登録、ルーティング、モデルバインディング、middlewareなど、実部品同士のつなぎ込みに関わる境界のこと。
環境の境界
ファイル権限、COM登録、32bit/64bit、STA/MTAなど、OSや実行環境の実挙動に関わる境界のこと。
時間の境界
timeout、cancellation、retryの実挙動、race conditionなど、時間と並行性に関わる境界のこと。
分岐の総当たり
クーポンの有無や在庫の有無など、条件分岐や入力パターンを網羅的に確認することのこと。
bitness一致要件
ネイティブモジュール(in-procのCOMコンポーネント、P/Invokeで呼ぶDLL、ベンダー提供SDKのDLLなど)を読み込むホストプロセスと、そのモジュールのビット構成(32bit/64bit)が一致していなければならないという制約。
32bit/64bitの一致
COMアパートメントモデル(STA/MTA)
どのスレッドからCOMコンポーネントを呼んでよいかを決める、COMのスレッドモデルの約束。
mockが増えすぎる兆候
mockが多数必要になる、setupが長い、arrangeが本体より長いなど、テストが読みにくくなっている兆候のこと。
3層のテスト構成
コア層をユニットテストで厚く、境界層を狭い結合テストで、全体層を少数のスモーク/E2Eで構成するテストの配置構成のこと。
コア層・境界層・全体層
E2Eテスト
デプロイ済みアプリや複数サービス、実ブラウザーを通してアプリ全体のユーザーフローを確かめるテストの層のこと。
機能テスト
テスト対象を協力オブジェクトから切り離す必要がある場合、入力条件を固定するためにコントロール可能な代役であるstubを使う。純粋関数や値オブジェクトのユニットテストには代役自体が不要で、stub・mock・fakeは目的に応じて使い分ける選択肢である
呼び出しが行われたこと自体をAssertの対象にしたい場合に、その検証のためmockを使う。純粋関数や値オブジェクトのユニットテストには代役自体が不要で、stub・mock・fakeは目的に応じて使い分ける選択肢である
軽量な代替実装で足りる場合にfakeを使う(stubやmockの総称として使われることもある)。純粋関数や値オブジェクトのユニットテストには代役自体が不要で、stub・mock・fakeは目的に応じて使い分ける選択肢である
JSON/CSVのシリアライズやDBのmappingなど、フォーマットの境界を確かめる主力として結合テストが本記事の推奨である
DI登録、ルーティング、モデルバインディングなど配線の境界を確かめる主力として結合テストが本記事の推奨である
ファイル権限、COM登録、32bit/64bit、STA/MTAなど環境の境界を確かめる主力として結合テストが本記事の推奨である
実際にtimeoutが効くか、cancellationが伝播するかなど時間の境界を確かめる主力として結合テストが本記事の推奨である
クーポンあり/なし、在庫あり/なしのように分岐条件が増える入力パターンの総当たりには、ユニットテストが本記事の推奨である
環境の境界には、32bit/64bitのビット数一致という制約の確認が含まれる(ファイル権限やCOM登録など他の懸念も環境の境界に含まれ、bitnessはそのうちの1つの例に過ぎない)
環境の境界には、STA/MTAのようなCOMのアパートメントモデルの確認が含まれる(COMやActiveXを含む構成の場合の例であり、環境の境界すべてにCOMアパートメントモデルが関わるわけではない)
mockによる呼び出し検証をユニットテストに積み重ねすぎると、mockが増えすぎる兆候につながることがある
DI登録やモデルバインディングなど配線の境界を、mockを積み重ねたユニットテストで確かめようとすることは、本物との接続の証明にならないため推奨されない
3層のテスト構成のコア層は、業務ルールや状態遷移をユニットテストで厚く持つ
3層のテスト構成の境界層は、DBやファイル、serializer、DIなどに狭い結合テストを置く
3層のテスト構成の全体層は、起動確認や主要フローを少数のスモーク/E2Eで押さえる
結合テストで入力パターンを総当たりすることは重くなりすぎるため推奨されず、代表的なシナリオへ絞ることが勧められている
in-memoryのfakeではファイル権限やCOM登録、32bit/64bitなど環境の境界の意味がかなり落ちるため、fakeをこの確認に用いることは推奨されない
wire formatのズレはfakeでは見つけにくいため、fakeをフォーマットの境界の確認に用いることは推奨されない