Shivam Bhatnagar
An overview of the Terraform Testing Framework with a focus on unit and integration tests. This post de-constructs the schema and shows how to setup tests which can help automate and improve testing for your infrastructure.
References
Terraform Testing != App Testing
– TF does not have functions or methods that can be tested
– Methods in TF e.g. lower() or toset() are baked into the binary and so it is NOT our responsibility to test
Terraform Test Framework (TTF)
This post does not cover Contract, End-End and Manual testing
1. Linting and Formatting
These types of tests answer the question can the Terraform engine parse the code correctly
While not on the test pyramid, you often encounter tests to verify the hygiene of your Terraform configuration. Use terraform fmt -check
and terraform validate
to format and validate the correctness of your Terraform configuration
2. Unit Testing
These types of tests answer the question does my config or plan contain the correct metadata
These should (usually) not be dependent on any external resources or API calls. If you do want to run a unit-test which creates infrastrucutre with TF apply then consider using the test mocking framework
Testing to make sure config renders as expected based on a given input. An example of this type of testing is when the TF config has conditional statements condition ? true : false
Suggestion : use in built validation as well as the unit testing capabilities that terraform offers i.e.
- Use core TF validation e.g. pre-conditions to check the value of an input variable
- Use a TF unit test to check the pre-condition is being correctly evaluated and behaves as expected
3. Integration Testing
These types of tests answer the question does my config successfully create resources
A terraform apply
offers limited integration testing because it creates and configures resources while managing dependencies. You should write additional tests to check for configuration parameters on the active resource.
An example of integration testing could be to check if a TF config correctly creates an S3 bucket and that it has KMS storage configured on it
Whilst this is possible with integration testing, a more robust suggestion for this type of test would be to use a tool like trivy
What could a CI/CD pipeline look like

What are alternatives ways to test TF?
- Terratest – written in GO
- kitchen-terraform – written in RUBY
Advantages of TTF
- TTF is written entirely in HCL (aka the same language as what TF uses)
- No added tooling or technologies
Structuring a test directory
terraform
│ main.tf
│ variables.tf
│
└───tests
│ │ my_first_test.tftest.hcl
│ │ my_second_test.tftest.hcl
│ │
│ └───setup
│ │ main.tf # test setup module - terraform block, variables, output block that can be referenced
How to define a test
File Name : my_file_name.tftest.hcl , also supports .json
Each test that is defined uses a run action which executes either a terraform plan or terraform apply (default is apply)
The order of the run statements is strictly followed
# example my_first_test.tftest.hcl
run "test_setup" {}
run "test1" {}
run "test2" {}
Each run has 1 or more assertions which checks a given condition and logs the result of that condition
assert {
condition = true | false
error = "My Error Message"
}
- If all the assertions of a test pass then the test passes
- If any of the assertions fail then the test fails
Each run can have variables defined within the scope of the test – these override the variable definition in the root module
variables {
test_var_1 = ABC
test_var_2 = 123
}
Provider Configurations can be defined within the scope of a test or test suite
# tests/setup/main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
# tests/my_first_test.tftest.hcl
provider "aws" {
region = "eu-west-2"
}
Mock data for certain resources and data sources – supported in v1.7 : https://developer.hashicorp.com/terraform/language/tests/mocking
Running tests
terraform test
Without arguments it will look for a folder names test and run any tests within it
Analogous to python testing – either all tests can be run in a suite or specific tests can be run in the test command