DEV Community

Mary Mutua
Mary Mutua

Posted on

Automating Terraform Testing: From Unit Tests to End-to-End Validation

Day 18 of my Terraform journey was one of the most exciting so far because it brought everything together: local testing, real AWS validation, and a CI/CD pipeline that runs automatically in GitHub Actions.

In Chapter 9 of Terraform: Up & Running, Yevgeniy Brikman explains that manual testing is necessary, but it does not scale. Once infrastructure grows beyond what one person can test by hand every time, you need automation that catches regressions early and gives the whole team confidence to move faster.

That was the focus of today.

I implemented all three layers of Terraform testing:

  • unit tests with terraform test
  • integration tests with Terratest
  • end-to-end tests with Terratest
  • a GitHub Actions workflow to run them automatically

GitHub reference:

👉 GitHub Day 18 Link

Why One Test Type Is Not Enough

One of the clearest lessons from today is that no single test layer is enough on its own.

If you only use unit tests:

  • they are fast and cheap
  • but they do not prove real AWS behavior

If you only use integration tests:

  • they prove module composition
  • but they still do not test the full stack from the outside

If you only use end-to-end tests:

  • they give the strongest confidence
  • but they are slower, more expensive, and harder to debug

The right strategy is to use all three.

Layer 1: Unit Tests with terraform test

Terraform 1.6+ includes native testing through .tftest.hcl files, which makes lightweight unit-style testing much easier.

For Day 18, I used terraform test to validate module behavior without creating any real infrastructure.

These tests checked things like:

  • ASG naming logic
  • instance type propagation
  • security group port configuration
  • variable validation for invalid environments

Example command:

terraform -chdir=day_18/modules/services/webserver-cluster test
Enter fullscreen mode Exit fullscreen mode

What I liked about this layer:

  • very fast
  • no AWS cost
  • no external dependencies
  • great for checking Terraform logic early

Tradeoff:

  • it does not prove that AWS will accept and run the infrastructure correctly

So unit tests are excellent for fast feedback, but they only cover part of the story.

Layer 2: Integration Tests with Terratest

The next layer was Terratest integration testing.

Here, the goal was to deploy real infrastructure and verify that the reusable modules worked correctly together in AWS.

For my integration test, I used:

  • the Day 18 webserver cluster module
  • a lightweight example root module
  • the default VPC as the test harness

The test:

  • applied the infrastructure
  • read outputs like alb_dns_name
  • sent HTTP requests to the deployed ALB
  • verified the expected response
  • destroyed the resources afterward

This gave me confidence that:

  • Terraform could really apply the stack
  • the ALB, ASG, target group, and alarms worked together
  • the app was actually reachable

Tradeoff:

  • slower than unit tests
  • creates real AWS resources
  • costs money
  • needs cleanup discipline

Still, this is the layer where Terraform starts moving from “logic looks right” to “real infrastructure works.”

Layer 3: End-to-End Tests with Terratest

The most complete layer was the end-to-end test.

Instead of using existing networking, this test deployed:

  • a fresh VPC
  • subnets
  • the webserver stack on top of that VPC
  • the full public application path

Then it verified that the final app response was correct from the outside.

This was the strongest test because it checked the complete system, not just a subset of it.

It also exposed a real issue:
my first end-to-end run failed because the subnet CIDRs did not fit inside the VPC CIDR range. AWS rejected them with an InvalidSubnet.Range error.

That was a very useful reminder that end-to-end tests often catch the kinds of real cloud issues that smaller tests miss.

After fixing the VPC CIDR input, the end-to-end test passed and cleaned up correctly.

Tradeoff:

  • slowest test layer
  • most expensive
  • most realistic
  • best confidence

This is why end-to-end tests are powerful, but you do not want to rely on them alone for every kind of feedback.

The CI/CD Pipeline That Ties It Together

After getting the local tests working, I built a GitHub Actions workflow to automate the testing pipeline.

The workflow runs:

  • unit tests on pull requests
  • unit, integration, and end-to-end tests on pushes to main
  • manual workflow runs when needed

That setup gave me a nice balance:

  • PRs stay faster and cheaper
  • merges to main get full confidence checks

One of the best parts of today was seeing the pipeline work the way it should:

  1. local tests passed
  2. the first GitHub Actions run failed
  3. I fixed the workflow
  4. opened a pull request from a feature branch
  5. PR checks ran
  6. merged into main
  7. GitHub Actions ran all three layers successfully

That was a great end-to-end learning moment for both Terraform testing and CI/CD.

What Each Layer Contributed

Here is how I now think about the testing stack.

Unit tests

Tool:

  • terraform test

Best for:

  • validation logic
  • naming
  • output expectations
  • fast feedback

Integration tests

Tool:

  • Terratest

Best for:

  • real AWS deployment checks
  • reusable module composition
  • output and connectivity verification

End-to-end tests

Tool:

  • Terratest

Best for:

  • full-stack confidence
  • fresh environment testing
  • user-visible behavior
  • catching real infrastructure wiring problems

That layered approach is what makes the whole system strong.

My Main Takeaway

The biggest lesson from Day 18 was this:

good Terraform testing is not about choosing one “best” test type.

It is about using the right mix of test layers for the right level of confidence.

  • unit tests are fast and free, but test less
  • integration tests are more realistic, but slower and costlier
  • end-to-end tests are the most thorough, but also the heaviest

The right strategy uses all three.

And once those tests are connected to CI/CD, infrastructure changes stop being something you only hope will work and start becoming something your pipeline can prove.

Full Code

GitHub reference:

👉 GitHub Day 18 Link

Follow My Journey

This is Day 18 of my 30-Day Terraform Challenge.

See you on Day 19.

Top comments (0)