terraform test — テストの書き方(Terraform 1.6+)

1. 概要

  • terraform testコマンドとは(Terraform 1.6+)
  • .tftest.hclファイルの書き方
  • assertブロックによる検証
  • モジュールのテスト
  • 実際のインフラを使ったテストとモック

Terraform 1.6で導入されたterraform testコマンドを使うと、TerraformコードをHCLのテストファイルで検証できます。モジュールの正確性を自動テストで保証し、リグレッションを防ぎます。


2. 基本的な使い方

# テストを実行(カレントディレクトリ内の*.tftest.hclを自動検出)
$ terraform test

# 特定のテストファイルのみ実行
$ terraform test -filter=tests/network.tftest.hcl

# 詳細出力
$ terraform test -verbose

テストファイルはtests/ディレクトリに.tftest.hcl拡張子で置きます。


3. テストファイルの基本構造

# tests/main.tftest.hcl

# テストで使う変数
variables {
  environment   = "test"
  instance_type = "t3.micro"
}

# run ブロック: 1つのテストケース
run "ec2_instance_created" {
  # commandはplan(デフォルト)またはapply
  command = plan

  # planの結果を検証
  assert {
    condition     = aws_instance.web.instance_type == "t3.micro"
    error_message = "インスタンスタイプがt3.microではありません"
  }

  assert {
    condition     = aws_instance.web.tags["Environment"] == "test"
    error_message = "Environmentタグが正しく設定されていません"
  }
}

4. テスト対象のモジュール例と完全なテスト

# modules/compute/main.tf(テスト対象)
terraform {
  required_version = ">= 1.6"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

variable "environment" {
  description = "環境名"
  type        = string
}

variable "instance_type" {
  description = "EC2インスタンスタイプ"
  type        = string
  default     = "t3.micro"
}

variable "vpc_id" {
  description = "VPC ID"
  type        = string
}

variable "subnet_id" {
  description = "サブネットID"
  type        = string
}

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = var.instance_type
  subnet_id     = var.subnet_id

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

output "instance_id" {
  value = aws_instance.web.id
}

output "private_ip" {
  value = aws_instance.web.private_ip
}
# modules/compute/tests/compute.tftest.hcl

provider "aws" {
  region = "ap-northeast-1"
}

# モックプロバイダー(実際のAWS APIを呼ばない)
mock_provider "aws" {
  mock_resource "aws_instance" {
    defaults = {
      id         = "i-mock1234567890"
      private_ip = "10.0.1.100"
    }
  }

  mock_data "aws_ami" {
    defaults = {
      id = "ami-mock1234567890"
    }
  }
}

variables {
  environment   = "test"
  instance_type = "t3.micro"
  vpc_id        = "vpc-test1234"
  subnet_id     = "subnet-test1234"
}

run "correct_instance_type" {
  command = plan

  assert {
    condition     = aws_instance.web.instance_type == var.instance_type
    error_message = "インスタンスタイプが変数と一致しません: ${aws_instance.web.instance_type}"
  }
}

run "correct_tags" {
  command = plan

  assert {
    condition     = aws_instance.web.tags["Environment"] == var.environment
    error_message = "Environmentタグが正しくありません"
  }

  assert {
    condition     = aws_instance.web.tags["ManagedBy"] == "terraform"
    error_message = "ManagedByタグが設定されていません"
  }

  assert {
    condition     = aws_instance.web.tags["Name"] == "${var.environment}-web"
    error_message = "Nameタグが正しくありません"
  }
}

run "ebs_encrypted" {
  command = plan

  assert {
    condition     = aws_instance.web.root_block_device[0].encrypted == true
    error_message = "EBSボリュームが暗号化されていません"
  }
}

5. テスト実行結果

$ terraform test

compute.tftest.hcl... in progress
  run "correct_instance_type"... pass
  run "correct_tags"... pass
  run "ebs_encrypted"... pass
compute.tftest.hcl... tearing down
compute.tftest.hcl... pass

Success! 3 passed, 0 failed.

6. mock_provider vs 実際のapply

方法速度コスト何をテストするか
command = plan高速無料設定値・タグ・型チェック
mock_provider高速無料planに近い検証(APIなし)
command = apply低速AWSコスト発生実際のリソース作成・属性

通常のCI/CDではplan + mock_providerでテストし、結合テストのみapplyを使います。


7. 関連記事


8. まとめ

  • terraform test(1.6+)で.tftest.hclファイルにテストケースを記述できる
  • assertブロックで変数・タグ・設定値の正確性を検証する
  • mock_providerでAWSへのAPI呼び出しなしに高速テストできる
  • command = applyで実際のリソース作成を検証できる(コスト注意)
  • モジュール開発にはテストを必ず組み込み、リグレッションを防ぐ

動作確認バージョン: Terraform >= 1.6 公式ドキュメント: https://developer.hashicorp.com/terraform/language/tests