Engineering Core
ISB Vietnam's skilled software engineers deliver high-quality applications, leveraging their extensive experience in developing financial tools, business management systems, medical technology, and mobile/web platforms.

Welcome to this article! If you are working with Terraform to manage cloud infrastructure such as AWS, writing integration tests is an important step to verify that your code works correctly with the real provider (for example, creating actual resources on the cloud). In this blog, I will guide you through creating integration tests (real-world application to check actual resources) for a simple Terraform source code: provisioning an EC2 instance via a module. We will use the Terraform Test feature (available from Terraform 1.6 onwards) to apply real code, validate outputs, and automatically destroy resources afterwards.

Project Structure

The source code we are working with follows a basic structure:

  • main.tf: The main file that calls the module and sets up the provider.
  • modules/ec2_instance/: The module that provisions the EC2 instance.
  • tests/integration.tftest.hcl: The integration test file.

1. Set Up Basic Terraform Source Code

First, create the project folder structure and files.

1.1 Create main.tf

This file configures the AWS provider and calls the EC2 module.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

module "web_server" {
  source = "./modules/ec2_instance"  # Adjust path if needed

  env_name      = "dev"
  instance_type = "t3.micro"
  ami_id        = "ami-0fa3fe0fa7920f68e"  # Replace with a valid AMI ID for your region
}

output "server_ip" {
  value = module.web_server.public_ip
}

 

1.2 Create the ec2_instance Module

Inside modules/ec2_instance, add the following files:

main.tf

resource "aws_instance" "web" {
  ami           = var.ami_id
  instance_type = var.instance_type

  tags = {
    Name = "web-server-${var.env_name}"
  }
}

output "public_ip" {
  value = aws_instance.web.public_ip
}

output "instance_type" {
  value = aws_instance.web.instance_type
}

output "ami" {
  value = aws_instance.web.ami
}

output "instance_state" {
  value = aws_instance.web.instance_state
}

 

variables.tf

variable "env_name" {
  description = "Environment name"
  type        = string
}

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
}

variable "ami_id" {
  description = "AMI ID for the EC2 instance"
  type        = string
}

 

Note: We add outputs such as instance_type, ami, and instance_state to make it easier to validate in integration tests (since internal resources are not directly exposed, and state is a computed value from AWS).

2. Introduction to Terraform Test

Terraform Test is an integrated framework for writing tests for Terraform code. For integration tests, it allows:

  • Real apply: Create actual resources on the cloud and validate them, with automatic destroy after the test finishes.
  • Run blocks: Execute commands such as apply or plan in a test environment.
  • Assertions: Validate conditions on outputs or resources.

To run tests, you need Terraform >= 1.6. Run terraform test from the project root. Tests will automatically run all .tftest.hcl files inside the tests/ folder.

3. Write Integration Test (Real Apply)

Integration tests apply real code to AWS, create actual resources, validate them, and destroy them afterwards. This helps verify that the code works correctly with the real provider.

Important notes:

  • You need valid AWS credentials (e.g., via environment variables such as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY).
  • This test will create (and destroy) real resources, so it may incur small costs (EC2 free tier may be free).

Create a tests folder and add integration.tftest.hcl.

run "integration_test_web_server" {
  command = apply

  assert {
    condition     = module.web_server.public_ip != null && module.web_server.public_ip != ""
    error_message = "Public IP should not be null or empty after apply."
  }

  assert {
    condition     = module.web_server.instance_type == "t3.micro"
    error_message = "Instance type does not match expected value."
  }

  assert {
    condition     = module.web_server.ami == "ami-0fa3fe0fa7920f68e"
    error_message = "AMI ID does not match expected value."
  }

  assert {
    condition     = module.web_server.instance_state == "running"
    error_message = "EC2 instance should be in running state."
  }
}

 

Explanation of the Integration Test File

  • run block: Executes apply with the real provider (no mock). Terraform will create an actual EC2 instance.
  • Assertions: Validate outputs (e.g., public_ip is not null, since now it’s a real value from AWS). Assertion on instance_state verifies the instance is running (a computed value from AWS).
  • Automatic cleanup: After the test finishes (pass or fail), Terraform will destroy the resource to avoid leftovers.

To run the integration test:

terraform test -filter=integration.tftest.hcl

Or run all tests:

terraform test

4. Run Integration Test

Run the command from the project root:

taipham@Tais terraform2 % terraform test
tests/intergration.tftest.hcl... in progress
  run "integration_test_web_server"... pass
tests/intergration.tftest.hcl... tearing down
tests/intergration.tftest.hcl... pass
tests/unit.tftest.hcl... in progress
  run "test_web_server_intance_type"... pass
  run "test_web_server_module_ami"... pass
  run "test_web_server_module_ami_ip"... pass
tests/unit.tftest.hcl... tearing down
tests/unit.tftest.hcl... pass

Success! 4 passed, 0 failed.

 

5. Best Practices for Integration Tests in Terraform

  • Limit usage: Use integration tests to verify real behavior, but limit them to avoid high costs (run in CI/CD with a dev account).
  • Meaningful assertions: Validate inputs, outputs, tags, and resource states (such as "running").
  • Integrate with CI/CD: Run terraform test in pipelines (e.g., GitHub Actions) for automation.
  • Advanced usage: Use expect_failures for negative tests or test multiple scenarios via variables.
  • Combine with unit tests: Add unit tests with mocks for faster checks; here we focus on integration.

Conclusion

With integration tests, you can verify that your Terraform code works correctly in real environments without leaving leftover resources. In this example, we tested an EC2 instance with minimal cost.

Whether you need scalable software solutions, expert IT outsourcing, or a long-term development partner, ISB Vietnam is here to deliver. Let’s build something great together—reach out to us today. Or click here to explore more ISB Vietnam's case studies.

[References]

https://developer.hashicorp.com/terraform
https://www.sudeepa.com/?p=382 [Image link]

Written by
Author Avatar
Engineering Core
ISB Vietnam's skilled software engineers deliver high-quality applications, leveraging their extensive experience in developing financial tools, business management systems, medical technology, and mobile/web platforms.

COMPANY PROFILE

Please check out our Company Profile.

Download

COMPANY PORTFOLIO

Explore my work!

Download

ASK ISB Vietnam ABOUT DEVELOPMENT

Let's talk about your project!

Contact US