12.03.20

Testing Your Code on Terraform: Terratest

By Gabriel Garrido

Infrastructure as Code (IAC) is more than just a paradigm. Developers are now able to deploy the code they have written on a capable cloud infrastructure without having to configure the cloud environment and provision resources manually. With the help of frameworks like Terraform, deploying supporting cloud infrastructure is as easy as writing a few lines of code.

As with other code constructing the app, however, infrastructure code can have faults and may cause errors. The need for improved testing⁠—including testing the resulting infrastructure itself⁠—is growing rapidly. For the longest time, developers relied on manual testing for the ‘solution’⁠—but that comes with its own set of inherent problems: it’s time-consuming, inefficient, and error prone. Terratest mitigates many of the issues in manual testing.

The Dangers of Manual Testing

Testing done early allows for the entire feedback loop to be shorter, which means errors and bugs can be caught before they ever reach production. Rather the firefighting, developers can anticipate errors and plug them early. At the same time, IAC allows for coding standards to be implemented from the beginning, which also means that maintaining a reliable infrastructure is easier.

Manual testing used to be the only way to test code, including infrastructure code. There is no way to do the testing locally or in a simulated environment. This means testing needs to be done in the cloud; that doesn’t just take more time, but also costs more as well. On top of that, manual testing doesn’t always reflect the automated process through which code is deployed.

There is another issue with manual testing, and that is the fact that multiple tests may be needed before code can be safely used and deployed. This, once again, forces developers to allocate more time and resources towards testing. It is one of the reasons why testing used to be seen as a nuisance or a difficult thing to do.

What Is Terratest?

Terratest is introduced as a way to create and automate tests. More specifically, it is a way to automate tests against your IAC code written in Terraform, Packer, and Docker. You can leverage the tools built into Terratest to validate that your infrastructure works efficiently in the right environment by making API calls, HTTP requests, SSH connections, etc. Test examples include end-to-end tests, test parallelism, unit tests, integration tests, static analysis, retries, error handling, and much more. It also works with providers like Amazon and Google and can be used to manage Kubernetes clusters.

Terratest eliminates the need for spooling up an entire cluster in order to test infrastructure code and saves a lot of time and money in the process. In some cases, you can save hours in waiting time alone. On top of that, Terratest simplifies the handling of errors and possible bug flagging.

The main goal of using Terratest is to make Terraform code testable. Terratest uses Go as the high-level language of choice, so anyone already familiar with Go can easily write a series of tests for their IAC code. You only need to run go test and Terratest will handle everything else, including init, apply, and destroy.

There are plenty of reasons why using Terratest is highly recommended, with the amount of money and time you can save the biggest reasons of them all. Aside from that, you also have the ability to test more complex infrastructure behaviors without having to manually provision cloud resources. Terratest automates end-to-end testing.

Terratest also eliminates the need for permanent testing infrastructure or multiple staging environments specifically for cloud infrastructure testing. Tests can be performed on-demand and at any stage of the development process, and a more consistent testing method can be implemented to ensure coding standards are maintained.

That last part also relates to the fact that Terratest allows for IAC code to be geared towards resilient infrastructure. In an era when everything is meant to be quick and agile, being able to test quickly and perform tests regularly are safety nets that prevent you from running into catastrophic errors. You can even validate AMIs.

Testing with Terratest

As mentioned before, testing using Terratest is as simple as running go test, but there are a few preparations to be made. Assuming you already have a Terraform code to work with, you only need to develop a testing framework for your infrastructure code. This involves defining some parameters that need to be passed through Terraform.

For example, you can define the variables using -var options.

Vars: map[string]interface{}{
			"aws_region":    awsRegion,
			"instance_name": instanceName,
			"instance_text": instanceText,
		}

There are a number of great test examples available to mimic on this Quick Start page by gruntwork.io to help you kick off your testing process. You also need to define how the testing ends, usually by using defer terraform.Destroy command to conclude the process. The rest is about identifying key parameters to test against, such as maxRetries and timeBetweenRetries if you want the test to also try multiple times when faced with infrastructure errors or inability to boot up.

The next part is performing unit testing using Terratest. While you can test the entire infrastructure code in one go, you still have the option to selectively test modules and units depending on your deployment type. For this, you need two things: a .tf with an abstract of the instance, and a Terratest configuration for testing that instance.

Multiple Tests

One more thing to understand about Terratest is how it is capable of conducting multiple specific tests. You can do more than just test the entire cloud infrastructure. You can for instance, test the IAM credentials of your AWS account to make sure that everything runs correctly. You can also test whether the instances have public IP addresses and whether those addresses are accessible from outside the cluster.

Terratest can even test files against certain parameters and strings. You can, for example, test specific files against a string using expectedText parameter within Terratest. In return, Terratest can be configured to display PASS/FAIL test results with additional details to help you fix errors. There is no limit to the number of parameters that you can test and you can use the client-go command to connect to an actual Kubernetes cluster created from the test and validate that resources are created in the cluster how we expect them to be.

HTTP requests, API calls, SSH connections, and other actions can all be added to the tests you create. Terratest will automate the execution of these actions to make sure that your cloud infrastructure is capable of supporting your application when you deploy the infrastructure code. Terratest certainly makes using IAC a more pleasant process.


Caylent provides a critical DevOps-as-a-Service function to high growth companies looking for expert support with Kubernetes, cloud security, cloud infrastructure, and CI/CD pipelines. Our managed and consulting services are a more cost-effective option than hiring in-house, and we scale as your team and company grow. Check out some of the use cases, learn how we work with clients, and read more about our DevOps-as-a-Service offering.