Terraform Fundamentals · Module 10 of 12

Validation, preconditions, checks and terraform test

Move infrastructure assumptions into executable validation using variable rules, lifecycle conditions, check blocks and Terraform tests.

Learning objectives

By the end of this module, you should be able to:

  • Choose between input validation, preconditions/postconditions and check blocks.
  • Understand that failing check blocks warn rather than block the operation.
  • Write and execute a provider-free terraform test.

Different validations run at different boundaries

Variable validation checks module inputs. Preconditions and postconditions enforce assumptions/guarantees around resources, data sources and outputs. They can block execution when conditions fail.

check blocks support continuous assertions

check blocks run after plan/apply validation and report warning diagnostics when assertions fail rather than blocking the operation. They are useful for ongoing infrastructure checks.

terraform test executes test files in isolated state

terraform test runs .tftest.hcl test files and uses state separate from the normal working state. Tests can plan or apply and make assertions. Tests that create real infrastructure can incur cost, so test accounts and cleanup matter.

Worked examples

See the idea in practice.

Provider-free Terraform test

// tests/name.tftest.hcl
run "name_contract" {
  command = plan

  variables {
    environment = "prod"
  }

  assert {
    condition     = output.name == "APP-PROD"
    error_message = "unexpected name"
  }
}
  • The test can validate root-module behavior without touching the normal state.
Hands-on lab

Lab — Add executable Terraform tests

Goal: Validate an input contract and output transformation with terraform test.

Before you start

  • Terraform 1.6+ is required for the stable terraform test workflow used here.
STEP 1

Create tested configuration

mkdir -p ~/gnu-terraform-labs/module10/tests && cd ~/gnu-terraform-labs/module10
cat > main.tf <<'EOF'
variable "environment" {
  type = string
  validation {
    condition     = contains(["dev", "prod"], var.environment)
    error_message = "use dev or prod"
  }
}

output "name" {
  value = upper("app-${var.environment}")
}
EOF
STEP 2

Write test file

cat > tests/name.tftest.hcl <<'EOF'
run "name_contract" {
  command = plan

  variables {
    environment = "prod"
  }

  assert {
    condition     = output.name == "APP-PROD"
    error_message = "unexpected name"
  }
}
EOF
STEP 3

Initialize

terraform init
STEP 4

Run tests

terraform test

Verify

  • The test run passes.
  • The normal working state is not required for the test.

Expected outcome

  • Infrastructure expectations are executable and can run in CI.

If it fails

  • terraform test can create real resources when tests use apply; isolate credentials and accounts accordingly.
  • A check block failure is a warning; use blocking validation when a failed invariant must stop the operation.
Real-world connection

Module tests and validation reduce regression risk before infrastructure changes reach production plans.

Avoid these traps

Common mistakes

  • Assuming check assertion failures block apply.
  • Running destructive module tests against production accounts.
  • Testing only syntax while ignoring behavioral outputs and invariants.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1Does a failing check block stop an apply?

No; it reports a warning and continues the operation.

2What can terraform test execute?

Plan or apply test runs with assertions using isolated test state.

3When is variable validation appropriate?

When an invalid module input should be rejected before infrastructure operations proceed.

My Learning

Record your progress for this module.

Progress is saved in this browser immediately. When you sign in to My Learning, it can also sync across devices.

Not started

Attempt the core lab and knowledge checks before marking the module complete.