Skip to content
CloudOps
All prompts
AI for Terraform Difficulty: Advanced ClaudeChatGPT

Terraform Module Testing Prompt

Test Terraform modules — terraform test (1.6+), terratest (Go), unit vs integration, mocking providers.

Target user
Engineers writing tests for Terraform modules
Difficulty
Advanced
Tools
Claude, ChatGPT

The prompt

You are a senior Terraform engineer who has built test suites for module libraries — integration tests with real cloud, unit-style tests, mocked providers.

I will provide:
- The module to test
- Current testing (if any)
- Goal

Your job:

1. **Terraform test (1.6+)**:
   - Built-in test framework
   - `.tftest.hcl` files
   - Run as `terraform test`
   - Native, easier than Go
2. **For terratest (Go)**:
   - Apply real infrastructure
   - Assert via cloud SDK
   - Destroy
   - Slow but thorough
3. **For unit-style** (no apply):
   - Plan-only checks
   - validate
   - Quick feedback
4. **For mocking providers** (1.7+):
   - Mock provider data
   - No cloud needed
   - Fast unit tests
5. **For test patterns**:
   - Smoke test (does it apply?)
   - Output verification
   - Side effect checks
   - Failure paths
6. **For CI integration**:
   - Run on PR
   - Cleanup on failure
   - Test environment isolation
7. **For sandbox account**:
   - Dedicated for tests
   - Cleanup via tags
   - Cost controls
8. **For test data**:
   - Fixtures
   - Random suffix to avoid collisions
   - Per-test unique

Mark DESTRUCTIVE: tests against production accounts (resource collisions), leftover test resources (cost), assertions hitting production data.

---

Module: [DESCRIBE]
Current testing: [DESCRIBE]
Goal: [DESCRIBE]

Why this prompt works

Modules without tests rot silently. This prompt walks options.

How to use it

  1. Use terraform test for new modules.
  2. Add terratest for thorough.
  3. Plan-only first, apply for integration.
  4. CI on PR.

Patterns

terraform test (native, 1.6+)

# tests/network.tftest.hcl

variables {
  vpc_cidr = "10.99.0.0/16"
  az_count = 2
}

# Test 1: plan only (fast)
run "plan_only" {
  command = plan

  assert {
    condition     = length(module.network.public_subnet_ids) == 2
    error_message = "Expected 2 public subnets for az_count=2"
  }
}

# Test 2: apply (real resources)
run "apply_and_verify" {
  command = apply

  assert {
    condition     = aws_vpc.main.cidr_block == "10.99.0.0/16"
    error_message = "VPC CIDR doesn't match input"
  }

  assert {
    condition     = length(aws_subnet.private) == 2
    error_message = "Expected 2 private subnets"
  }
}

# Test 3: validation should fail with invalid input
run "validate_input" {
  command = plan

  variables {
    vpc_cidr = "not-a-cidr"
  }

  expect_failures = [
    var.vpc_cidr,
  ]
}
terraform test
terraform test -filter=tests/network.tftest.hcl
terraform test -verbose

Mocked provider (1.7+, native unit test)

# tests/with_mocks.tftest.hcl

mock_provider "aws" {
  mock_resource "aws_vpc" {
    defaults = {
      id         = "vpc-mock-12345"
      cidr_block = "10.0.0.0/16"
    }
  }
}

run "test_with_mocks" {
  command = plan

  assert {
    condition     = module.network.vpc_id == "vpc-mock-12345"
    error_message = "Mocked VPC ID not returned"
  }
}

terratest (Go, integration)

// test/network_test.go
package test

import (
    "testing"

    "github.com/gruntwork-io/terratest/modules/aws"
    "github.com/gruntwork-io/terratest/modules/terraform"
    "github.com/stretchr/testify/assert"
)

func TestNetwork(t *testing.T) {
    t.Parallel()

    region := "us-east-1"

    terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
        TerraformDir: "../examples/basic",
        Vars: map[string]interface{}{
            "vpc_cidr": "10.99.0.0/16",
            "az_count": 2,
        },
        EnvVars: map[string]string{
            "AWS_DEFAULT_REGION": region,
        },
    })

    defer terraform.Destroy(t, terraformOptions)

    terraform.InitAndApply(t, terraformOptions)

    vpcID := terraform.Output(t, terraformOptions, "vpc_id")
    assert.NotEmpty(t, vpcID)

    // Verify via AWS SDK
    vpc := aws.GetVpcById(t, vpcID, region)
    assert.Equal(t, "10.99.0.0/16", *vpc.CidrBlock)

    subnetIDs := terraform.OutputList(t, terraformOptions, "private_subnet_ids")
    assert.Len(t, subnetIDs, 2)
}
cd test
go mod init my_org/network_test
go get github.com/gruntwork-io/terratest/modules/terraform
go test -v -timeout 30m

CI integration (GitLab)

test-module:
  image: hashicorp/terraform:1.9
  variables:
    AWS_DEFAULT_REGION: us-east-1
    # Account: sandbox; cleanup tagged
  before_script:
    - export AWS_ACCESS_KEY_ID=$SANDBOX_AWS_ACCESS_KEY_ID
    - export AWS_SECRET_ACCESS_KEY=$SANDBOX_AWS_SECRET_ACCESS_KEY
  script:
    - cd modules/network
    - terraform test -verbose
  artifacts:
    when: always
    paths: [test-results/]
  after_script:
    # Cleanup leaked resources
    - ./scripts/cleanup-sandbox.sh

Test patterns

PatternWhen
Plan-onlyFast feedback, validate logic
Apply + verifyIntegration, real cloud
Mocked providerUnit tests, no cloud
Negative testsValidation rules
IdempotenceApply twice; no changes second

Common findings this catches

  • Tests skip apply → false confidence.
  • Test resources leaked → cleanup script.
  • No negative tests → invalid input passes.
  • Tests too slow for PR → split.
  • Parallel test collisions → unique IDs.
  • Mocked provider returns canned data → catches schema errors but not logic.
  • CI auth in plaintext → masked variables.

When to escalate

  • Cloud test infrastructure — eng / finance.
  • Test framework migration — staged.
  • Cross-team module test standards — coordinate.

Related prompts

Newsletter

Get weekly AI workflows for DevOps engineers

Practical prompts, automation ideas, and tool reviews for infrastructure engineers. One email per week. No spam.