このコラムの主なテーマは、信頼できる実行結果にできるだけ短い時間でたどり着く自動テスト群の構築です。本稿では、テストダブルをうまく活用してテストピラミッドを構築する戦略を立てます。
信頼性の高い自動テスト群を求めて
自動テスト全体の中長期的な信頼性を守るために、図1のようにLargeからMediumへ、MediumからSmallへテストサイズを適宜下げ、テストピラミッドを構築します[1]。テストサイズとは、単一プロセスに閉じたテストをSmall、単一マシンに閉じたテストをMedium、そういった制約がないテストをLargeテストと呼ぶ分類基準です。
サイズダウンを考えるとき、テストダブルの活用が思い浮かびます。テストダブルとは、自動テストに使用する偽物、代用品のことです。単一プロセスや単一マシンに収まらない外部依存を偽物に置き換え、テストサイズを下げます[2]。
テストダブルと互換性
テストダブルによって自動テストの実行速度や決定性
互換性とは、ある部品やコンポーネント
機能互換はソース互換よりも到達が難しく、一般にソース互換であっても機能互換ではない状況は多々あります。ただし、テストダブルにおいては、テストから使用する部分が機能互換であれば実用上は問題ありません。
互換性は、バージョンアップ時に失われることがあります。バージョンアップのタイミングは、管理できるものもあれば
以上、互換性の視点から整理すると、ソース互換と機能互換という異なるレベルの互換性において、最初から互換性がない
段階1:テストダブルを使わない
忠実性をできるだけ下げずにサイズダウンするには、テストダブルを使わない、作らない、工夫して作る、という順番で検討します。
まず、偽物に置き換える前に、本物がそのまま使えないかを調べます。本番環境ではマシンをまたぐ外部依存がMediumやSmallに収まるならば、忠実性をほぼ下げずにサイズダウンできます。たとえば、MySQLやRedisなどの公式イメージや、自社のバックエンドチームが開発しているイメージをコンテナで動かせば、サイズがMediumに収まります。ただし、イメージが本物であっても忠実性が100%ではないことに注意しましょう。設定内容やマシンスペック、ネットワーク構成などは異なり、それがLargeテストとの差分です。
次に、設計の改善を検討します。たとえば、抽象化によってレイヤを分け、結合度を減らし、テストダブルで置き換えたい依存がコードに登場する箇所が少なくなれば、ピラミッドの中段や下段でテストを書きやすくなります。良い設計を行うと、Smallテストで書ける範囲が自然と広がります。
段階2:テストダブルを作らない
テストダブルを使わざるを得ないと判断したら、次は互換性を意識して忠実性の低下を抑えます。多くの場合、自動テストの作者は置き換え対象の作者ではないので、テストダブルを作ってもソース互換性はまだしも機能互換性の高さは期待できません。
そこで、テストダブルを自分で作る前に、
フェイクはテストダブルの一種で、自動テスト用の軽量な代替実装です。信頼のおける開発元が作成したフェイクは、仕様の誤解や理解のずれに起因する非互換が少なくなります。
まず公式のフェイクを探します。フェイクの提供者が置き換え対象の開発元であるならば、高い機能互換性が期待できます。たとえば、DynamoDBに対応したDynamoDB localは、ローカル開発用にAWS
公式のフェイクが見つからない場合、OSSのフェイク実装を探します。公式ではなくとも、OSSとして多数の利用者の目にさらされているフェイクは高い機能互換性を期待できます。たとえば、LocalStackプロジェクトはAWSの各サービスのフェイクを提供し、多くの開発者に使われています。
段階3:テストダブルを工夫して作る
探しても見つからなかった場合は、互換性が失われたタイミングをとらえられるように工夫してテストダブルを作ります。
テストダブルで置き換える対象を自社の別チームが開発している場合などでは、静的なスキーマをチーム間の仕様策定に使い、ソース互換性の喪失に備えます。機能互換性に関しては、中央のスキーマからテストコードとフェイクを生成してチーム間で共有するPactなどのConsumer-driven Contract(CDC) Testingのしくみを導入したり、開発元のチームにテスト用のフェイク提供を依頼したりすれば、高い機能互換性を期待できます。チーム間でのフェイクの共有は、追随が必要な機能変更を自動テストの失敗として伝えられるメリットがあります。
管理できない外部依存のテストダブルを作るときは、外部通信を記録して再生できるVCRなどのRecord & Replay型のテスト支援ライブラリを導入し、Largeテストで本物と通信した内容を記録しておき、それをテストダブルとしてSmallテストで再現できるようにします。記録内容を定期的に更新すれば、互換性が失われたことを検知できます。
おわりに
テストダブルを作る前に、まず使わないですまないか、作らずにすまないかを確認しましょう。