Setting up infrastructure manually can be both time-consuming and challenging. This is where Infrastructure as Code (IaC) tools come into play, offering automation for provisioning and managing infrastructure. With IaC, automation is achieved for setting up resources like virtual machines, storage, and more. As infrastructure increasingly becomes code, implementing unit and integration tests becomes crucial to ensure its reliability. This blog explores what IaC is and why testing it matters, followed by a detailed look at using Terratest for infrastructure testing.
Let’s dive in!
What is Infrastructure as Code (IaC)?
Infrastructure as Code refers to the practice of automating the provisioning and configuration of infrastructure using code, rather than manually setting it up through a graphical interface. For instance, virtual machines can be defined and deployed, configured, and integrated with monitoring systems—all through code. Examples of IaC tools include Terraform, Packer, and Ansible.
IaC allows tracking infrastructure changes in version control systems like Git, creating reusable templates and modules, and deploying consistent configurations across multiple environments and regions. One of the major benefits of IaC is disaster recovery, as it enables quick replication of infrastructure in different environments or regions when needed.
What is Terratest?
- Testing Docker images, Helm charts, and Packer templates.
- Interacting with cloud provider APIs, including AWS and Azure.
With Terratest, both basic sanity checks and detailed functional tests can be conducted on infrastructure code. This tool helps identify and resolve issues efficiently within infrastructure configurations. Additionally, Terratest supports compliance testing, ensuring that infrastructure components, such as newly created S3 buckets, adhere to best practices like enabling versioning and encryption.

Advantages of Testing Infrastructure as Code (IaC)
Infrastructure as Code (IaC) has become a cornerstone of modern cloud infrastructure management, allowing teams to automate the provisioning and management of infrastructure using code. However, just like any software application, IaC must be tested to ensure that it functions correctly and securely in a production environment. Here are some key reasons why testing IaC is essential:
1. Testing helps catch configuration errors early, preventing costly issues in production.
2. Ensures the same infrastructure setup in development, staging, and production environments.
3. Validates security configurations, preventing vulnerabilities like misconfigured access control.
4. Automated tests in CI/CD pipelines allow for faster, more reliable infrastructure changes.
Pre-requisite to run the Terratest
To run Terratest for testing Infrastructure as Code (IaC) in this blog, ensure the following prerequisites are met:
1. Go Lang (Version 1.20 or Above): Terratest is built using Go, requiring version 1.20 or higher. The current Go version can be checked by running:
go version2. Terraform:Since this blog focuses on testing Terraform code, having Terraform installed is essential. The Terraform version can be checked with:
terraform versionSetting Up Terratest for Terraform
Now we will execute some integration tests using terratest. Once the installation steps are complete, We’ll start by writing the test using Go and execute it.
Setup the file structure
Writing a Test with Terratest
Here’s an example test for an AWS S3 bucket using Terratest:
1. Terraform Configuration
# main.tf
resource "aws_s3_bucket" "example" {
bucket = var.bucket_name
acl = "private"
}
# variables.tf
variable "bucket_name" {
description = "The name of the S3 bucket."
}
# outputs.tf
output "bucket_name" {
value = aws_s3_bucket.example.bucket
}2. Test Code
// test/main_test.go
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
func TestS3BucketCreation(t *testing.T) {
t := testing.T()
// Define Terraform options
terraformOptions := &terraform.Options{
TerraformDir: "../",
Vars: map[string]interface{}{
"bucket_name": "terratest-example-bucket",
},
}
// Ensure infrastructure is destroyed after test
defer terraform.Destroy(t, terraformOptions)
// Run Terraform Init and Apply
terraform.InitAndApply(t, terraformOptions)
// Get output values
bucketName := terraform.Output(t, terraformOptions, "bucket_name")
// Assert bucket name matches expected value
assert.Equal(t, "terratest-example-bucket", bucketName)
}Now, run the terraform init command. After that go to test directory and run the following commands to run the test:
go mod init <module-name> //e.g. terratest-test
go mod tidy
go test -vAfter running this command, the logs can be viewed where Terratest checks the Terraform code and identifies any errors or vulnerabilities, if present.
Conclusion
Terratest bridges the gap between IaC and software testing, enabling teams to validate infrastructure with confidence. By incorporating Terratest into workflows, robust, reliable, and cost-effective infrastructure provisioning can be ensured. Starting small, iterating, and gradually expanding test coverage allows for achieving the full benefits of IaC testing.