Testing modules with terraform test

Terraform · Advanced · 12 min

Shared modules are code that many teams depend on; they need automated tests too.

terraform test runs test files (*.tftest.hcl, in the module root or tests/). Each file contains run blocks executed in order:

  • command = plan checks the plan only: fast and needs no real infrastructure for many assertions.
  • command = apply (the default) actually creates the resources, runs assertions, and destroys everything at the end of the file.
  • variables { ... } at file or run level set inputs.
  • assert { condition = ... error_message = ... } blocks check outputs and resource attributes, e.g. aws_s3_bucket.this.bucket == "acme-logs".
  • expect_failures = [var.env] asserts that validation rejects bad input: test your error paths.
  • module { source = "./tests/setup" } in a run block uses a helper module, for example to create prerequisites or to load a fixture.

Mocking (mock_provider "aws" {} in a test file) replaces a provider with one that returns fake values, so even apply-style tests run in seconds without credentials. Combine: unit-style tests with mocks on every commit, real-apply integration tests nightly in a sandbox account.

Run with terraform test, or terraform test -filter=tests/naming.tftest.hcl for one file. Results print pass/fail per run block.

Terratest (Go) remains an option for complex end-to-end checks, such as making HTTP requests to what you deployed.

Example

# tests/bucket.tftest.hcl  (module from the modules lesson)
mock_provider "aws" {}

variables {
  name = "acme-logs-test"
}

run "versioning_enabled_by_default" {
  command = plan
  assert {
    condition     = aws_s3_bucket_versioning.this.versioning_configuration[0].status == "Enabled"
    error_message = "Versioning should default to Enabled"
  }
}

run "can_disable_versioning" {
  variables { versioning = false }
  assert {
    condition     = aws_s3_bucket_versioning.this.versioning_configuration[0].status == "Suspended"
    error_message = "versioning = false should suspend versioning"
  }
}
# terraform test
# tests/bucket.tftest.hcl... pass  (2 passed, 0 failed)

Remember

  • run blocks with command = plan or apply, plus assert blocks
  • expect_failures tests validation errors
  • mock_provider makes tests fast and credential-free

Watch out for

  • Running apply-mode tests in a production account; use a sandbox, since tests create real resources.

Check yourself

  1. What happens to resources created by apply-mode run blocks when the test file finishes?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.hashicorp.com/terraform/language/tests