Testing of software is nothing new, of course. But testing of (Azure) cloud infrastructure as code deployments follows a little bit another approach. I recently started to work with this testing and write about my impressions, the general testing strategies in that area and how it works.
Testing for “normal” software und IaC deployment code is a bit different. Therefore, a little overview of what the tech world defines, following the general dividing of test areas from Unit Test to E2E test and how it could be mapped to IaC testing:
- Can be seen on our module units. For some people, it’s just verifying the code with terraform plan (and stop there)
- other try to parse the generated plan and investigate the data further (search for specific resources)
- or you have the complete test (including cloud deploy) for the module, asserting afterwards deployed resources
- complete testing of modules
- combining multiple modules in a testing script, work with dependencies (output from a module is input for another)
End 2 end-test
- similar scenario like integration test
- deployment of complete environments
- because of time needed for the deployments, the environments are not destroyed after the test. It’s like deploying resources with Terraform or ARM templates and only the deltas are deployed or deleted. But that’s expensive for testing purposes.
Find more details under: terraform/best-practices
Here’s a cool video covering the test scenarios:
Testing with Terratest framework from Gruntwork.io
Terratest is a testing framework, written in Go. It can be used to write tests for the Terraform deployments. With some configuration done, you can script the steps for Terraform which you usually do manually:
The framework also supports you with methods to check for an existing resource or with helpers to perform http calls, for example.
Steps needed to work with Go:
- install the Go language package: install go
- Go extension for Visual Studio Code: vs code go
- Init the test module
- Create test files end with _test.go
- run test locally (or in pipelines)
If you perform all testing steps, the authentication must work for 2 parts! (see usage tipps)
- deploy the resurces via Terraform
- access the subscription with Terratest (not needed if you stop at the plan step)
To get started with Terratest, check: quick start
Don’t forget to switch to your test folder.
Inside, start the test. You can either start all test in the folder for files ending with _test.go, or pick a specific one naming a specific file. Use the verbose flag (-v) to get details. It is also recommended to set a timeout lasting longer than the standard 10 minutes from Go testing, because it’s not unusual for real infrastructure deployments to need some time.
go test -v -timeout 30m go test -v -timeout 30m myfancytest_test.go
For writing the tests, check modules for details on the available modules to investigate the deployed resources.
Find some simple code examples, also for other providers like AWS: terratest examples
or check the whole Terratest repo on Github: gruntwork-io/terratest
For downloading missing packages defined in your test scripts but not yet available on your local machine, you can use
go mod tidy
In opposite to the official documentation, I needed to setup other environment variables to get the Terratest access working (meaning the second authentication part, to search within the already deployed resources through terraform apply for asserting):
os.Setenv("AZURE_CLIENT_ID", "abc") os.Setenv("AZURE_CLIENT_SECRET", "123") os.Setenv("AZURE_TENANT_ID", "456")
(The documentation tells to set up ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_SUBSCRIPTION_ID and ARM_TENANT_ID). The values are from the created Azure Service Principal.
If just running terraform validate & plan is enough, you might not need Terratest. You can include these steps in a DevOps pipeline, for example. But if you like the confidence of having deployed the correct resource or setting, then this framework is a very nice approach to write your tests.
I think I’m not at the end of the journey and still have some issues with the framework. For example, using Dep for dependency managing on my windows machine actually doesn’t work and a good-looking tutorial for testing through parsing the created Terraform plan file is unfortunately outdated, using packages not existing anymore (docs.microsoft)
Following other approaches / packages for serious plan parsing didn’t lead to success so far. But hey, don’t give up (-:
Next things I’ll try is to setup the testing in a DevOps pipeline using containers…
Nice post. Thanks for sharing!