Cleanup & defer destroy

Never leak real resources.

Advanced10 min · lesson 4 of 12

The single most important habit in Terratest is reliable cleanup, and the idiom is defer terraform.Destroy placed immediately after Options, before Apply. Go runs deferred calls when the function returns — including when an assertion fails or the test panics — so putting Destroy in a defer guarantees teardown runs no matter how the test ends. Skip it, or place it after the assertions, and a failing test leaves real resources (and a real bill) behind.

pattern
func TestThing(t *testing.T) {
opts := &terraform.Options{ TerraformDir: "../examples/thing" }
defer terraform.Destroy(t, opts) // FIRST — runs even if apply/asserts fail
terraform.InitAndApply(t, opts)
// ... assertions that might fail ...
}

When cleanup itself fails

Destroy can fail too — a dependency still in use, a resource stuck deleting, an eventual-consistency race. Guard against leaks in depth: use unique names/tags per test run so orphans are identifiable, run tests in a dedicated sandbox account you can periodically sweep, and add a scheduled cleanup job (e.g. cloud-nuke) that removes anything older than a few hours matching the test tag. Belt and suspenders, because a leaked NAT gateway or RDS instance quietly costs money for weeks.

unique naming
import "github.com/gruntwork-io/terratest/modules/random"
name := "test-" + strings.ToLower(random.UniqueId()) // unique per run
opts := &terraform.Options{
TerraformDir: "../examples/thing",
Vars: map[string]interface{}{ "name": name, "tags": map[string]string{"terratest":"true"} },
}
// a scheduled cloud-nuke sweeps anything tagged terratest older than N hours
A leaked test resource bills until someone notices
The failure mode of infra testing is not a red test — it is a green-ish run that left an expensive resource behind that nobody sees for a month. Always defer Destroy first, tag every resource for identification, isolate tests in a sandbox account, and run a scheduled sweep. Assume cleanup will occasionally fail and design so leaks are caught and reaped, not accumulated.