IaCのテストは「全部やる」ものではなく、コストと価値のバランスで段を選ぶものです。速くて安い検査を下に厚く、遅くて高い統合テストを上に薄く。テストピラミッドの発想をIaCに翻訳し、CIのどの段でどれを回すかを整理します。

「IaCにテストは要るのか」という問いは、もう終わっています。数百行のTerraformが本番のネットワークやIAMを一発で書き換える以上、テストなしでapplyを押すのは、コンパイルせずに本番デプロイするのに近い。問題は「やるか否か」ではなく「どこまでやるか」です。本稿では、海外で確立したテストピラミッドの発想をIaCに翻訳し、静的解析・plan検証・統合テストをCIのどの段で回すか、コストと価値のバランスとして整理します。

01IaCのテストピラミッド — 下に厚く、上に薄く

アプリケーションのテストピラミッド(下から単体・結合・E2E)は、IaCにもそのまま効きます。下ほど「速く・安く・数多く」、上ほど「遅く・高く・少なく」。IaCの場合、この軸は「実インフラを作るか否か」とほぼ一致します。fmtやlintは秒で終わりゼロコスト、plan検証はクラウドAPIを叩くが破壊はしない、統合テストは実際にリソースを立てて壊すため分単位で課金が発生します。

現場のコツ:「ピラミッドの各層を全部埋める」ことが目的ではありません。多くのエンタープライズは第1層と第2層を厚くするだけで、事故の大半を止められます。第3層は「共有モジュール」など再利用され壊れると影響が広い対象に絞るのが費用対効果の勘所です。

統合テスト terraform test(apply)/Terratest plan検証・policy test plan diff + OPA/Conftest terraform test(plan/mock) 静的解析 fmt / validate / tflint / checkov 遅い 高コスト 速い 低コスト
図:IaCのテストピラミッド。下層ほど速く安く数多く、上層ほど遅く高く少なく。

02第1層 — fmt / validate は「ゼロコストの門番」

最下層はTerraform同梱の2つから始めます。terraform fmt -check はフォーマットの揺れをCIで弾き、レビューを差分の本質だけに集中させます。terraform validate は構文と内部整合(未定義変数、型不一致、必須引数の欠落など)を、クラウドに接続せずにチェックします。どちらも数秒・課金ゼロ・依存なしで、入れない理由がありません。

ただしvalidateは「文法的に正しいか」しか見ません。「そのインスタンスタイプがそのリージョンに存在するか」「非推奨の書き方をしていないか」までは踏み込まないため、次のlintが必要になります。

03第1層 — 静的解析:tflint(品質)とcheckov(セキュリティ)は役割が違う

ここで混同されがちなのがtflintcheckovです。両者は補完関係で、片方では足りません。

tflintリンターです。terraform validateより踏み込み、プロバイダ固有の誤り(存在しないインスタンスタイプ、非推奨構文、未使用の変数宣言など)をapply前に検出します。Terraform言語ルールはTFLint本体に同梱され、AWSルールセットだけでも700以上のルールが提供されます。.tflint.hclpreset = "recommended"を指定すれば推奨ルールに絞れます。

checkovセキュリティ・コンプライアンススキャナです。「公開S3バケット」「暗号化されていないボリューム」「過剰なIAM権限」といった設定ミスを、AWS/Azure/GCP向けに1,000以上の組み込みポリシーで検査します(公式Quick Start参照)。導入はcheckov -d . のように一行です。CIS/PCI-DSS等のフレームワーク準拠チェックも持ちます。

現場のコツ:checkovは初回スキャンで大量の指摘が出て、チームが「ノイズ」と感じて無効化しがちです。全部を一度に直そうとせず、--checkで重大なものから段階導入し、正当な例外は行内のskipコメントに理由付きで記録するのが現実的です。「なぜ無視したか」が残らない抑制は、半年後の監査で必ず問題になります。

04第2層 — plan検証:diffそのものを検査対象にする

静的解析はコードを見ますが、plan検証は「これから何が起きるか」を見ます。ここがIaCテストの独自性です。terraform plan -out=tfplan.binary でバイナリplanを生成し、terraform show -json tfplan.binary > tfplan.json で機械可読なJSONに変換します。このJSONにはresource_changes(全変更)やchange.actions(create/update/delete)が含まれ、「実際に適用されるとどう変わるか」がモジュールやデフォルト値も解決済みの形で入っています。

これをOpen Policy Agent(OPA)とそのCLIラッパーconftestでRegoポリシーにかけます。コードのHCLではなくplanのJSONを見るため、「モジュール経由で最終的にどうなるか」を検査できるのが強みです。OPA公式のTerraform例では、削除・作成・変更を重み付けした「blast_radius(影響半径)」スコアを計算し、閾値を超える危険なplanや、IAMを変更するplanを自動で拒否する例が示されています。

terraform plan -out=tfplan show -json tfplan.json OPA / Conftest Regoで検査 合格 → apply 違反 → 停止
図:plan検証フロー。planをJSON化しRegoで検査、合否でapplyを制御する。

05第2〜3層 — terraform test:HCLで書く公式テストフレームワーク

Terraform 1.6以降、terraform testという公式のテストフレームワークが同梱されました(公式ドキュメント)。新しい言語を覚える必要はなく、.tftest.hclファイルにHCLでrunブロックとassertブロックを書きます。ポイントはrunブロックのcommandで、ピラミッドの層を切り替えられることです。

さらにTerraform 1.7ではプロバイダのモックが導入され、実クラウドに接続せずにより詳細な単体テストが書けるようになりました。OpenTofuでも同等のtofu testが提供され、.tftest.hcl/.tofutest.hclを実行します(OpenTofu公式)。「テスト用に別言語(Go)を持ち込みたくない」チームには、この公式フレームワークが第一候補になります。

06第3層 — Terratest:実インフラを立てて本当に動くか確かめる

より踏み込んだ検証、たとえば「立てたWebサーバに実際にHTTPリクエストが通るか」「SSHでログインできるか」まで確かめたい場合は、Gruntwork社のTerratestが定番です(公式ドキュメント)。Goで_test.goを書き、①実IaCツールで実環境にデプロイ→②HTTP/API/SSH等で振る舞いを検証→③最後に破棄、という流れを回します。Gruntwork自身が30万行超のIaCライブラリを保守するために生まれたツールで、実運用の重みがあります。

現場のコツ:統合テストは「実リソースを立てる=課金と時間が発生する」層です。専用のサンドボックスアカウントで回し、deferによる破棄を必ず入れ、失敗時にリソースが残り続けないようにします。全モジュールに統合テストを課すとCIが遅く高くなりすぎるので、共有・再利用されるモジュールに限定するのが現実解です。マルチアカウント環境での分離設計はマルチアカウント統制の考え方と合わせて設計してください。

07CIのどの段で何を回すか — 速い順に、落ちるなら早く

ツールが揃ったら、CIパイプラインに「速い順」で並べます。原則はfail fast。安くて速い検査を前段に置き、そこで落ちれば高い統合テストまで進ませない。これがコストと待ち時間を最小化します。

plan結果をPRに可視化してレビュー材料にする運用は、AWSも新しいTerraform Test Frameworkと組み合わせて推奨しています(AWS DevOpsブログ)。State運用や環境昇格そのものは、IaCパイプライン設計の別テーマとして切り出して検討するのが整理しやすいです。

08コストと価値のバランス — 「全部やる」は正解ではない

最後に、SIer/エンタープライズの現場でいちばん効く話をします。テストは投資であり、青天井にやれば赤字になります。第1層(静的)は限界コストほぼゼロなので全リポジトリで必須。第2層(plan検証・policy)は、組織の禁止事項(公開バケット禁止、特定リージョン外禁止、IAM変更は要承認など)をコード化する価値が高く、統制の中核になります。ここまでは投資対効果が明確です。

迷うのは第3層です。統合テストは最も高価で、維持コスト(壊れやすいテストのメンテ)も無視できません。「全モジュールに統合テスト」を掲げると、たいてい形骸化します。影響範囲が広い共有基盤モジュールに絞り、それ以外はplan検証+policyで止める。この線引きこそがテスト戦略の本体です。DevOpsの成熟度を測るなら、テストの本数ではなく変更のリードタイムや変更失敗率で見るべきで、その観点はDORAとDeveloper Experienceで整理しています。なお具体的なバージョン挙動や課金は変わりうるため、導入前に公式ドキュメントで要確認としてください。

まとめ

IaCのテストは「やるか否か」ではなく「どこまでやるか」です。fmt/validate/tflint/checkovの静的層を全リポジトリで厚く敷き、plan検証+OPA/Conftestで組織の禁止事項をコード化し、統合テスト(terraform testのapplyやTerratest)は共有モジュールに絞る。テストピラミッドの発想でCIに「速い順・fail fast」に並べれば、待ち時間もコストも抑えつつ事故の大半を止められます。「全部やる」ではなく、現場の制約に合わせた賢い線引きを。

参考(一次情報)

IaCのテスト設計やCIパイプラインの段構成でお困りの際は、お問い合わせください。現場の制約に合わせて「どこまでやるか」を一緒に線引きします。

相談する
← ブログ一覧へ戻る