top of page
Writer's pictureRafael Natali

How to test your Terraform code

Updated: Aug 11, 2023

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

Terraform testing

This post was originally posted at Medium and presented at HashiBuild: Talks 2022 conference.

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 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.

References

  1. https://www.hashicorp.com/blog/testing-hashicorp-terraform

  2. https://www.terraform.io/language/modules/testing-experiment

  3. https://medium.com/marionete/using-terraform-to-manage-multiple-gcp-resources-c5b432a6d619


27 views0 comments

Comments


bottom of page