Terratest, hands-on

In this article I´m going to show how to manage and interact with a very basics working example of Terratest, the idea is to have a first Terraform + Terratest working prototype.

Let´s start with a very basic example of a working Terraform project, the structure and function is very simple, different declared variables that will output different predefined values.


data "template_file" "example" {template = var.example}data "template_file" "example2" {template = var.example2}resource "local_file" "example" {content  = "${data.template_file.example.rendered} + ${data.template_file.example2.rendered}"filename = "example.txt"}resource "local_file" "example2" {content  = data.template_file.example2.renderedfilename = "example2.txt"}


output "example" {value = data.template_file.example.rendered}output "example2" {value = data.template_file.example2.rendered}output "example_list" {value = var.example_list}output "example_map" {value = var.example_map}output "example_any" {value = var.example_any}

When this code is run locally it will show the following output

Outputs:example = "example"
example2 = "test"
example_list = tolist([])
example_map = tomap({})

Now we need to focus on Terratest, the project structure should include one folder with all the Terraform files, in my case “examples”, and one separated folder, in this case “test”, at the same level where to run the Terratest files

├── examples
│ ├── README.md
│ ├── example.txt
│ ├── example2.txt
│ ├── main.tf
│ ├── outputs.tf
│ ├── terraform.tfstate
│ ├── terraform.tfstate.backup
│ ├── terraform.tfvars
│ ├── variables.tf
│ └── versions.tf
└── test
├── Gopkg.lock
├── Gopkg.toml
├── go.mod
├── go.sum
├── terraform_basic_example_test.go
└── vendor

Make sure the go project has the correct setup, It should be placed in the right go project workplace, I´m my case I´ve created a go folder where all the packages and modules are placed and the go-workspace and inside src/testings I´ve placed all the Terraform and Terratest files needed

├── go
│ └── pkg
│ ├── mod
│ │ ├── cache
│ │ ├── cloud.google.com
│ │ ├── github.com
│ │ ├── golang.org
│ │ ├── google.golang.org
│ │ ├── gopkg.in
│ │ ├── k8s.io
│ │ └── sigs.k8s.io
│ └── sumdb
│ └── sum.golang.org
└── go-workspace
├── bin
├── pkg
│ ├── dep
│ │ └── sources
│ ├── mod
│ │ ├── cache
│ │ ├── github.com
│ │ ├── golang.org
│ │ └── gopkg.in
│ └── sumdb
│ └── sum.golang.org
└── src
└── testings
├── examples
└── test

Now when the setup is done let´s take a look to the go file, this file will generate all the infrastructure defined in Terraform and do the necessary testings, in this case we need to make sure the outputs have the right values.

package testimport ("testing""github.com/gruntwork-io/terratest/modules/terraform""github.com/stretchr/testify/assert")// An example of how to test the simple Terraform module in examples/terraform-basic-example using Terratest.func TestTerraformBasicExample(t *testing.T) {t.Parallel()expectedText := "test"expectedList := []string{expectedText}expectedMap := map[string]string{"expected": expectedText}terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{// website::tag::1::Set the path to the Terraform code that will be tested.// The path to where our Terraform code is locatedTerraformDir: "../examples",// Variables to pass to our Terraform code using -var optionsVars: map[string]interface{}{"example": expectedText,// We also can see how lists and maps translate between terratest and terraform."example_list": expectedList,"example_map":  expectedMap,},// Variables to pass to our Terraform code using -var-file optionsVarFiles: []string{"varfile.tfvars"},// Disable colors in Terraform commands so its easier to parse stdout/stderrNoColor: true,})// website::tag::4::Clean up resources with "terraform destroy". Using "defer" runs the command at the end of the test, whether the test succeeds or fails.// At the end of the test, run `terraform destroy` to clean up any resources that were createddefer terraform.Destroy(t, terraformOptions)// website::tag::2::Run "terraform init" and "terraform apply".// This will run `terraform init` and `terraform apply` and fail the test if there are any errorsterraform.InitAndApply(t, terraformOptions)// Run `terraform output` to get the values of output variablesactualTextExample := terraform.Output(t, terraformOptions, "example")actualTextExample2 := terraform.Output(t, terraformOptions, "example2")actualExampleList := terraform.OutputList(t, terraformOptions, "example_list")actualExampleMap := terraform.OutputMap(t, terraformOptions, "example_map")// website::tag::3::Check the output against expected values.// Verify we're getting back the outputs we expectassert.Equal(t, expectedText, actualTextExample)assert.Equal(t, expectedText, actualTextExample2)assert.Equal(t, expectedList, actualExampleList)assert.Equal(t, expectedMap, actualExampleMap)}

To execute Terratest just need to run this command

go test -v -run TestTerraformBasicExample

Will execute the Terraform project, generate de IaC, check based on the tests we´ve defined and finalize with a PASS or FAIL message

--- PASS: TestTerraformBasicExample (5.48s)
ok testings/test 5.684s




Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Debian 9 Kernel Version

Challenges I encountered in Selenium test automation: Part 1

Why buy an Alexa if you can make your own?

LeetCode — Longest Common Sequences

Azure Data Factory — Azure REST API in your data pipelines

FFmpeg: Add a logo on video

5 Side Project Ideas for Web Developers

2021 FIM Motocross World Championship MXGP of Turkey : Livestream | LIVE° [Fullᴴᴰ]

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

Lucas B.


More from Medium

Infrastructure as Code: Is it so hard?

From Planning to Production: DevSecOps Best Practices for Completely Secure Solutions

DevSecOps Best Practices

Kubernetes, why YOU need to know about them!

Kubernetes Logo

A Day in the life of a Multi Site packet on a Cisco ACI Hybrid Multi Cloud Environment (Azure)