100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
HCL

Terraform Testing Frameworks

Survey the tools used to test Terraform code — from the built-in `terraform test` command to Terratest and Kitchen-Terraform — and when each fits into a testing strategy.

Testing & QualityAdvanced10 min readJul 9, 2026
Analogies

Terraform Testing Frameworks

Testing infrastructure code is fundamentally different from testing application code: the 'unit under test' often involves real cloud resources, billing, and eventual consistency delays. Terraform's testing ecosystem has matured to cover this spectrum — from fast, local, no-provider assertions to full end-to-end tests that stand up real infrastructure, verify behavior, and tear it down. Choosing the right tool depends on how much confidence you need versus how much time and cost you're willing to spend per test run.

🏏

Cricket analogy: Testing infrastructure code, where the unit under test involves real cloud billing and delays, is like testing a new bat design: you can check its weight and balance in the nets quickly, but only a real match innings under actual pressure gives full confidence.

terraform test (native)

Since Terraform 1.6, the native terraform test command runs .tftest.hcl files containing run blocks that apply a configuration (or a mocked variant), assert on outputs and resource attributes, and optionally tear everything down automatically at the end. It supports both unit-style tests using the command = plan mode (no real resources touched) and full integration tests using command = apply, all without leaving the Terraform toolchain.

🏏

Cricket analogy: The native terraform test command with .tftest.hcl run blocks is like a franchise's in-house net session that can either simulate a bowler's line and length without a real batter (plan mode) or run a full practice match with real scoring (apply mode), all within the club's own facility.

hcl
# tests/vpc.tftest.hcl
variables {
  cidr_block = "10.0.0.0/16"
}

run "plan_creates_expected_cidr" {
  command = plan

  assert {
    condition     = aws_vpc.main.cidr_block == "10.0.0.0/16"
    error_message = "VPC CIDR block did not match expected value"
  }
}

run "apply_creates_valid_vpc" {
  command = apply

  assert {
    condition     = length(aws_vpc.main.id) > 0
    error_message = "VPC was not created with a valid ID"
  }
}

Terratest and Kitchen-Terraform

Terratest, a Go library from Gruntwork, gives full programmatic control: it runs terraform apply, then uses Go code (and cloud SDKs) to make real assertions — e.g. actually curling an endpoint the infrastructure created, checking an S3 object exists, or verifying an autoscaling group has the right instance count — before automatically destroying everything with a deferred cleanup call. Kitchen-Terraform, built on Test Kitchen, follows a similar apply-verify-destroy lifecycle but integrates with InSpec for declarative compliance-style assertions. Both are heavier-weight than native terraform test but allow assertions the native tool cannot express, since they run arbitrary code against live infrastructure.

🏏

Cricket analogy: Terratest is like a franchise hiring an independent analytics firm to actually attend the match, clock real ball speeds, and verify the boundary rope distance in person before signing off, then leaving once the report is filed — heavier than a scorecard review but able to check things a scorecard can't.

bash
$ go test -v -timeout 30m ./test/vpc_test.go
=== RUN   TestVpcModule
INFO  Running command terraform init
INFO  Running command terraform apply -auto-approve
INFO  VPC created: vpc-0a1b2c3d4e5f6789
--- PASS: TestVpcModule (184.32s)
PASS

A useful mental model: native terraform test in plan mode is like a unit test (fast, no real resources), terraform test in apply mode and Terratest are like integration tests (real resources, real assertions, real teardown), and policy-as-code checks are like static analysis run on every plan.

Integration-style tests that actually apply infrastructure cost real money and take real time (often minutes) per run — always ensure teardown runs even on assertion failure (Terratest's defer terraform.Destroy(...) pattern), or you'll leak billable orphaned resources.

  • Native terraform test runs .tftest.hcl files with run blocks in either plan mode (fast, no resources) or apply mode (real resources).
  • Terratest (Go) and Kitchen-Terraform (Ruby/InSpec) provide full programmatic assertions against real, deployed infrastructure.
  • Plan-mode tests act like unit tests; apply-mode tests act like integration tests with real cost and time overhead.
  • Always ensure teardown runs even when an assertion fails, to avoid leaking billable orphaned resources.
  • Choose native terraform test for most cases; reach for Terratest when you need to assert against live external behavior (HTTP endpoints, SDK calls).
  • A layered strategy — fast plan-mode tests plus fewer, targeted apply-mode tests — balances confidence against cost and runtime.

Practice what you learned

Was this page helpful?

Topics covered

#HCL#TerraformInfrastructureAsCodeStudyNotes#DevOps#TerraformTestingFrameworks#Terraform#Testing#Frameworks#Test#StudyNotes#SkillVeris