Terraform: How to write unit tests for your infrastructure code

Updated: February 3, 2024 By: Guest Contributor Post a comment

Overview

As the adoption of Infrastructure as Code (IaC) accelerates, ensuring the reliability and correctness of infrastructure definitions becomes paramount. Terraform, a leader in this space, allows the definition of infrastructure through code. However, like any code, it is subject to human error. The solution? Unit tests. This tutorial will guide you through writing unit tests for your Terraform code, covering everything from basic to advanced techniques.

Unit Testing in Terraform

Unit testing involves testing individual units of source code to determine if they are fit for use. In the context of Terraform, this means validating whether your infrastructure modules behave as expected. This step is crucial before proceeding to apply these configurations to live environments. Unlike traditional software development, where the output is often a functioning program, Terraform’s output is the configuration of infrastructure. Therefore, the testing frameworks and methodologies differ slightly.

Tools for Terraform Testing

Several tools facilitate Terraform testing:

  • Terratest: A Go library that allows you to write automated tests for your infrastructure code.
  • Terraform Testing Framework (TTF): A new entrant, focused on providing a more standardized method for Terraform testing.
  • TestKitchen: Integrates with Terraform to enable a more comprehensive testing strategy, including unit, integration, and acceptance tests.

This tutorial will primarily focus on Terratest due to its wide adoption and robust feature set.

Getting Started with Terratest

Before diving into test writing, ensure you have Go installed on your system, as Terratest is a Go library. Once you’ve set up your environment, initiate a new Go project:

mkdir terraform-unit-testing && cd terraform-unit-testing
go mod init terraform-unit-testing
go get github.com/gruntwork-io/terratest/modules/terraform

With your project initialized, you can now begin crafting your first test.

Writing Your First Test

Start by creating a new Go file, `vpc_test.go`, in your project directory:

package test
import (
  "testing"
  "github.com/gruntwork-io/terratest/modules/terraform"
)
func TestVPC(t *testing.T) {
  terraformOptions := &terraform.Options{
    // The path to where your Terraform configuration files are located
    TerraformDir: "../vpc",
  }

  // Clean up resources with defer after testing
  defer terraform.Destroy(t, terraformOptions)

  // Initialize and apply Terraform
  terraform.InitAndApply(t, terraformOptions)

  // Write assertions here to validate the correctness of your infrastructure code
}

This basic test initializes and applies a Terraform configuration for a Virtual Private Cloud (VPC), then cleans up the resources afterward. You can extend this test with assertions to verify the configuration’s correctness, such as checking if the VPC has the expected CIDR block.

Advanced Testing Strategies

As you grow more comfortable with basic testing, you can explore more advanced strategies.

  • Mocking External Dependencies: Often, infrastructure code interfaces with external systems. Mocking these can isolate your tests, ensuring they only validate your code’s logic.
  • Testing Across Modules: Complex infrastructure often consists of multiple Terraform modules. Testing these in isolation and together ensures integrations function as expected.
  • Stress Testing: Stress tests validate how your infrastructure performs under load, identifying potential scaling issues.

Example: Testing Across Modules

Let’s say you have two modules: a VPC and a database. Your application requires that these two interact securely. A comprehensive test might involve provisioning both modules and asserting network configurations ensure secure communication.

package test

// Import statements...

func TestVPCAndDBIntegration(t *testing.T) {

  // Terraform options for both VPC and database modules

  // Apply both modules

  // Assertions to verify correct network settings
}

This example demonstrates the power of Terraform unit testing in validating complex, integrated infrastructure setups.

Conclusion

Unit testing your Terraform code is essential for maintaining scalable, reliable infrastructure. The techniques outlined in this tutorial provide a foundation, but the depth and breadth of testing should evolve with your infrastructure’s complexity. Adopting sound testing practices early ensures your IaC is as robust as the infrastructure it provisions.