Skip to main content
RunBook Academy

TerraformXXI · Testing, Linting, and Static AnalysisTesting

terraform test: The Native Test Framework

Advanced⏱ ~12 min🧪 Lab requiredbashterraform

What you'll learn

  • Use terraform test to write unit tests
  • Use plan tests to verify resource changes
  • Use mock providers to test without real resources
  • Recognise when terraform test is appropriate

Prerequisites

Verified against Terraform CLI 1.9.x · OpenTofu 1.7.x · HCL 2.0 · bpg/proxmox provider 0.66+ · hashicorp/local provider 2.5+ · hashicorp/null provider 3.2+ · hashicorp/random provider 3.6+ · hashicorp/http provider 3.4+ · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · 2026-08-12

Not yet marked complete on this device.

terraform test is the native test framework for Terraform. It runs .tftest.hcl files that contain test blocks. The tests can be unit tests, plan tests, or integration tests. The lesson teaches the test framework and the production patterns.

Test files

A terraform test run discovers *.tftest.hcl files in the current directory:

tests/
├── main.tftest.hcl
├── outputs.tftest.hcl
└── variables.tftest.hcl

Each file contains a sequence of run blocks:

# tests/main.tftest.hcl

run "test_greeting_is_hello" {
  command = plan

  expect {
    resources = {
      local_file.hello = {
        content = "Hello, world!\n"
      }
    }
  }
}

The run block:

  • Specifies the command (plan or apply).
  • Specifies the expected outputs (expect block).

The test commands

The command argument can be:

  • plan — runs terraform plan and inspects the result.
  • apply — runs terraform apply and inspects the result.

The plan command is read-only. The apply command modifies the real world (or the mock providers).

The expect block

The expect block specifies the expected output:

run "test_greeting_content" {
  command = plan

  expect {
    resources = {
      local_file.hello = {
        content = "Hello, world!\n"
      }
    }
  }
}

The expect block can match:

  • resources — the resources in the plan.
  • outputs — the outputs in the plan.
  • inputs — the variables passed to the module.
  • state — the state (for apply tests).

Mock providers

For unit tests, mock providers are used to avoid real resources:

# tests/greeting.tftest.hcl

mock_provider "local" {
  mock_resource "local_file" {
    defaults = {
      filename = "/tmp/hello.txt"
      content  = "Hello, world!\n"
    }
  }
}

run "test_greeting_with_mock" {
  command = plan

  expect {
    resources = {
      local_file.hello = {
        filename = "/tmp/hello.txt"
        content  = "Hello, world!\n"
      }
    }
  }
}

The mock provider returns the configured defaults. The test runs without real resources.

The plan test

The plan test verifies the plan matches the expectation:

run "test_plan_no_changes" {
  command = plan

  expect {
    # No changes expected
    changes = {}
  }
}

The test fails if the plan is not empty.

The apply test

The apply test verifies the real-world matches the configuration:

run "test_apply_creates_file" {
  command = apply

  expect {
    resources = {
      local_file.hello = {
        filename = "/tmp/hello.txt"
        content  = "Hello, world!\n"
      }
    }
  }
}

The apply test creates a real resource. The test cleans up the resource after the run.

The test runner

The test runner:

# Run all tests
terraform test

# Run a specific test file
terraform test tests/main.tftest.hcl

# Run with verbose output
terraform test -verbose

# Run with a specific filter
terraform test -filter test_greeting

The output:

tests/main.tftest.hcl... in progress
  run "test_greeting_is_hello"... pass
  run "test_greeting_content"... pass
tests/main.tftest.hcl... pass

Success! 2 passed.

The production pattern

A production Terraform module has tests:

modules/network/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
└── tests/
    ├── main.tftest.hcl
    ├── outputs.tftest.hcl
    └── variables.tftest.hcl

The tests are:

  • Unit tests with mock providers.
  • Plan tests with the actual configuration.
  • Apply tests with the actual configuration.

The tests run in CI. The tests are the production control for the module.

What comes next

The next lesson is lintingtflint and the production control for configuration style.

Verification

Knowledge check · 7 questions

  1. Q1. What is the role of the layered testing model?

  2. Q2. What is terraform test?

  3. Q3. terraform test is a separate tool that requires installation.

  4. Q4. What is the role of mock providers in tests?

  5. Q5. Which of the following are part of the layered testing model? (Select all that apply.)

  6. Q6. What is the role of the plan test in terraform test?

  7. Q7. A terraform test fails. What is the next step?

Passing score: 75%. Answers are checked in this browser.