Marionete
Published in

Marionete

How to test your Terraform code

Learn about the HashiCorp Terraform Module Testing Experiment configuration and how to use it to run tests against infrastructure.

Testing Terraform code

Testing is vital to understand if the infrastructure code we created is doing what they are supposed to. Running a terraform plan helps, but it’s not a guarantee. The best way is to deploy the resources in a controlled manner.

Terratest and kitchen-terraform both pioneered the idea of writing tests for Terraform modules with explicit orchestration written in the Go and Ruby programming languages, respectively.

Since Terraform CLI v0.15.0 Hashicorp introduced an experimental testing module, this is what I’d like to talk about it.

Writing Tests for a Module

I’ll use a Terraform code that creates buckets in GCP as the source. You can find the code in this GitHub repository and a detailed explanation in this Medium article.

I want to test whether the Terraform is creating a bucket. So, my test will be to create a bucket and verify the execution by comparing the bucket’s name.

First, configure the outputs.tf file to output the bucket name:

output “bucket_name” {
value = google_storage_bucket.bucket.name
}

Second, make sure your variables.tf has a default value assigned to each variable.

Third, within the terraform-google-cloud-storage/cloud-storage-module create a new sub-folder tests/defaults. In the defaults directory, create a defaults.tf file.

The tests/defaults/defaults.tf file will contain a call to the main module with a suitable set of arguments and resources that will, for the sake of the experiment, serve as the temporary syntax for defining test assertions. For example:

module "main" {  
# source is always ../.. for test suite configurations,
# because they are placed two subdirectories deep under
# the main module directory.
source = "../.." # This test suite is aiming to test the "defaults" for
# this module, so it doesn't set any input variables
# and just lets their default values be selected instead.
}

The following code is the test assertion configuration:

# The special test_assertions resource type, which belongs
# to the test provider we required above, is a temporary
# syntax for writing out explicit test assertions.
resource "test_assertions" "bucket" {
# "component" serves as a unique identifier for this
# particular set of assertions in the test results.
component = "bucket" equal "bucket_name" {
description = "default bucket_name is natali-test-eu-627"
got = module.main.bucket_name # value from the output
want = "natali-test-eu-627"
}
}

In the equal block, I’m comparing the bucket name that the main module outputted (got) with the value I defined in the variables.tf (want). If they match, the test ran successfully.

Running the tests

The terraform test command is an experimental command to help with automated integration testing of shared modules. Terraform operations similar to the following sequence of commands:

  • terraform validate
  • terraform apply
  • terraform destroy

In this example, navigate to the terraform-google-cloud-storage/cloud-storage-module folder and execute terraform test:

$ terraform test

Success! All of the test assertions passed.

To force an error, I change the want value in the test without changing the value in the variables.tf

──────────────────────────────────────────────────────── 
Failed: defaults.bucket.bucket_name
(default bucket_name is natali-test-eu-627) ────────────────────────────────────────────────────────
wrong value
got: "natali-test-eu-627"
want: "natali-test-eu-628"

Known Limitations

As an experimental module, there are a few limitations on how it works. At the time of writing (March, 2022) the two main limitations I’d like to highlight are:

  • Currently tests written in this way can only exercise the create and destroy behaviours.
  • Unit testing without creating real objects. You cannot test against non-real resources.

Please, refer to the Hashicorp documentation for a complete list.

--

--

--

Working at the edge of what‘s possible

Recommended from Medium

Organize your Big Data Pipeline using Airflow

Contract Law in Utah

Software Engineering Bootcamp

Ateneo Blue Eagles in Google Developer’s DSC Summit in Malaysia

Ordinary user to Developer: The Android Learning Community memoir.

Dealing With Life’s Uncertainty, The Programmer’s Way

Make bash as default terminal in VSCode

How Do Web Browsers Work?

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Rafael Natali

Rafael Natali

AWS | GCP | Terraform | Kubernetes — linkedin.com/in/rafaelnatali

More from Medium

Terraform — How to organize your terraform code

The Best IaC Tool to Use in DevOps 2022

Managing Secrets on Terraform

wall with several safe boxes

The Modern DevOps Toolbox. Part 3 of 3.