Terraform (IaC) Testing

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.

  1. Use core TF validation e.g. pre-conditions to check the value of an input variable
  2. 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?

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

Leave a Comment

Your email address will not be published. Required fields are marked *