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.
# 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.
$ 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)
PASSA 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 testruns.tftest.hclfiles withrunblocks in eitherplanmode (fast, no resources) orapplymode (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 testfor 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
1. What file extension do native Terraform test files use?
2. In native `terraform test`, what is the key difference between `command = plan` and `command = apply` in a run block?
3. What language is Terratest written in and used with?
4. Why must integration-style Terraform tests guarantee teardown even on assertion failure?
5. What does Kitchen-Terraform integrate with for declarative compliance-style assertions?
Was this page helpful?
You May Also Like
terraform validate and fmt
Understand two everyday Terraform commands — `terraform fmt` for consistent code style and `terraform validate` for catching syntax and configuration errors before you ever run a plan.
Terraform in CI/CD Pipelines
Learn the standard stages, safety controls, and credential-handling patterns for running Terraform reliably inside a CI/CD pipeline, from plan-on-PR to gated apply-on-merge.
Writing a Reusable Module
Turning ad-hoc configuration into a well-designed reusable module requires thoughtful input/output design, sensible defaults, and internal structure. This topic walks through the practical craft of module authoring.
Drift Detection
Understand configuration drift — when real infrastructure diverges from Terraform state — and the tools and practices used to detect and reconcile it before it causes surprises.
Related Reading
Related Study Notes in DevOps
Browse all study notesNginx Study Notes
DevOps · 30 topics
DevOpsAnsible Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsAdvanced Bash Scripting Study Notes
Bash · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsDocker & Kubernetes Study Notes
YAML · 40 topics