1.5.1. Testing

In daily development, we are accustomed to running tests immediately after writing code to ensure functionality works as expected. However, when we enter the world of Terraform, things are not that simple. Terraform is a tool used to manage infrastructure, and its "code" directly impacts cloud resources such as servers, databases, and networks. Executing terraform apply can incur actual costs and may even impact production environments.

Therefore, Terraform's testing strategy requires special care. We cannot perform comprehensive tests on every combination of parameters like we do with ordinary programs, as this is not only time-consuming but can also lead to high costs. Furthermore, Terraform presents a unique challenge: state management. If terraform plan still shows changes when there are no configuration modifications, it indicates that "configuration drift" has occurred, which we must avoid.

Even more complex is Terraform's sensitivity to version upgrades. If we release a non-major version update (e.g., upgrading from 1.2.3 to 1.3.0) that introduces breaking changes, it could cause issues for users' infrastructure. Consequently, we need to ensure that every update does not negatively impact existing users.

In this chapter, we will explore how to conduct effective testing in Terraform. Whether you are a Terraform novice or an experienced developer, you will find practical advice and techniques here.

This chapter will primarily introduce how to design testing frameworks and testing strategies, without delving into specific testing tools. We will cover different types of testing tools in detail in the subsequent tools chapters.

1.5.1.1. Types of Terraform Module Testing

When maintaining and governing large-scale Terraform modules (such as Azure Verified Modules), building a systematic testing strategy is crucial. This chapter will introduce five common Terraform testing types within AVM to help you ensure module stability, compliance, and maintainability.

1.5.1.2. Unit Testing

Unit testing focuses on validating whether the smallest functional units in a module work as expected, typically performed without deploying actual resources. By simulating input variables and using the terraform plan command, you can check if the resource configuration meets expectations. For example, you can verify if a variable's value correctly affects a resource's attributes. Terraform v1.6 introduced a native testing framework, allowing the use of .tftest.hcl files to write test cases, further simplifying the writing and execution of unit tests.

Sometimes, through Symbolic Links and Override Files, we can also bypass heavy Providers and cloud API calls to perform lightweight verification of complex logic that may exist in Terraform code.

1.5.1.3. End-to-End Testing

End-to-End (E2E) testing simulates the actual deployment process to verify if the behavior of the entire deployed infrastructure meets expectations. These tests are usually conducted in an isolated test environment by deploying a full resource stack. They can also verify system functionality through actual operations (such as network connectivity tests, API calls, etc.). Tools like Terratest (based on Go) or Terraform's native testing features can help you write and execute such tests, ensuring potential issues are discovered before deployment to the production environment.

1.5.1.3.1. Drift Detection

Drift detection is used to identify differences between the actually deployed infrastructure and the Terraform state, ensuring configuration consistency. By running the terraform plan command, changes not managed by Terraform can be detected. This test is often run in conjunction with end-to-end testing to ensure that the infrastructure does not trigger configuration drift due to internal reasons after deployment.

1.5.1.3.2. Breaking Change Testing

Breaking change testing aims to prevent the introduction of changes that would break existing module callers during non-major version updates (i.e., minor or patch versions). According to Semantic Versioning principles, incompatible changes should only be introduced during major version updates.

We can add a type of breaking change test to verify if the changes in the current PR will have a destructive impact on existing module callers. If errors or unexpected changes are detected during the terraform plan stage, it indicates that the PR introduces incompatible changes, and the merge should be postponed or upgraded to a major version update.

This testing strategy helps automatically detect potential breaking changes in the Continuous Integration (CI) process, ensuring module stability and backward compatibility. In subsequent chapters, we will detail how to implement this testing process and integrate it into our DevOps workflow.

1.5.1.4. Linting

Linting aims to ensure that Terraform configuration files are syntactically correct, clearly structured, and follow best practices. Tools like TFLint, terraform validate, and terraform fmt can automatically detect syntax errors, inconsistent naming, or potential configuration issues. By integrating these tools into the Continuous Integration (CI) process, issues can be captured and fixed before code merging, improving code quality and maintainability.

1.5.1.5. Compliance Testing

Compliance testing is used to ensure that infrastructure configurations meet organizational policies and regulatory requirements. For example, verifying whether all resources contain necessary tags or if security settings like encryption are enabled. Tools like Checkov, Conftest, and Sentinel (for Terraform Enterprise) can help us define and enforce compliance policies, automatically detecting violations in configurations.

results matching ""

    No results matching ""