Back to Blog
Terratest
Terragrunt

Terratest 1.0 Released!

James
Kwon
,
Software Engineer
May 11, 2026

After a decade of development, hundreds of releases, and infrastructure tested across every major public cloud, Terratest 1.0 is officially here.

Why release Terratest 1.0?

Terratest has been in 0.x throughout its history because the API has been unstable, partly because Terragrunt's was too. With the release of Terragrunt 1.0, that is no longer a blocker, and we can finally make compatibility guarantees in Terratest. Going forward, you can upgrade across releases without breaking changes in minor versions. Breaking changes will be restricted to major releases, which will happen infrequently.

What 1.0 Means

From this release forward, Terratest follows semantic versioning. Symbols renamed or replaced inside the v1 line stay compiled and callable, marked with a // Deprecated: annotation that names its successor, so go vet, staticcheck, and your IDE list the upgrades for you instead of leaving you to grep a changelog. Full removal is deferred to v2. You can pin to v1 and trust that minor and patch upgrades will not break your tests. (The 0.x to 1.0 jump itself does include breaking changes, called out in Upgrading from 0.x below.)

Beyond the stability promise, 1.0 ships four substantive changes:

  • Context plumbing throughout: every cloud-API helper now takes an explicit context.Context as its second argument, so timeouts, cancellation, and tracing finally have an idiomatic place to plumb through what is otherwise a wall of long-running cloud calls.
  • Mockable SDK clients: most Azure and GCP helpers that previously hid SDK client construction now have a WithClient sibling that takes an injected client, so you can drive Terratest against Azure's azfake server or a GCP test double and write fast unit tests with zero credentials.
  • Modern, supported underlying SDKs: archived legacy SDKs (Azure's "track 1" SDK, AWS s3/manager) and two archived direct dependencies are gone. Security fixes upstream now reach you.
  • Long-standing footguns gone: EC2 list calls paginate (used to silently cap at 1,000 results), concurrent OPA policy downloads deduplicate via singleflight, RDS/ACM/OCI/Azure list paths return errors instead of panicking on empty responses, and GCP SetMetadata merges instead of clobbering. If you have ever debugged a flaky Terratest run, one of these probably caused it.

The Context migration is the most pervasive of the four. In practice:

// Before
terraform.Apply(t, options)

// After
terraform.ApplyContext(t, t.Context(), options)

FooContext (fail-fast) and FooContextE (returns the error) are the canonical entrypoints going forward; the non-Context variants stay as deprecated aliases for now. The reliability fixes in the last bullet are technically behavior changes too: if your tests asserted on the prior pagination cap or panic semantics, re-run them against v1.

Upgrading from 0.x

Prerequisites: Go 1.26 or newer.

Most changes in 1.0 are backwards compatible: legacy functions still work and emit deprecation warnings pointing at their replacements. Adopt the new APIs at your own pace.

Four changes at the 0.x to 1.0 boundary may require code edits:

  • Azure SDK migration: modules/azure moved off Microsoft's archived "track 1" SDK onto the actively maintained sdk/resourcemanager. Anyone who imports the Azure SDK directly will have imports, type names, and list iteration to update.
  • AWS S3 uploader: the NewS3Uploader* helpers changed return type after s3/manager was deprecated upstream. Affects callers that drive the uploader directly.
  • GCP Pub/Sub: modules/gcp/pubsub.go moved to pubsub/v2. Wrapper shapes are unchanged, but direct client callers switch to the new admin clients.
  • Kubernetes kubeconfig: a typo'd KubectlOptions.ConfigPath used to silently fall back to in-cluster authentication. v1 logs the load error and adds an explicit opt-in.

After upgrading, run go mod tidy from your test module's directory; AWS, Azure, and GCP SDK pins all moved in 1.0.

For specifics, see the v1 migration guide.

When is 2.0?

The release of 2.0 is in active development. We have changes we have wanted to ship for a while that need to land in a major release. The headline is a structural one: 2.0 is expected to split Terratest's modules into independent Go modules, so consumers no longer pull in the Azure, GCP, and Kubernetes SDKs as transitive dependencies of a project that only uses, say, modules/aws.

For most users, the upgrade should be as small as adding a /v2 suffix to your imports. If you have a test like this today:

import (
    "testing"

    "github.com/gruntwork-io/terratest/modules/terragrunt"
    "github.com/stretchr/testify/require"
)

func TestTerragruntExample(t *testing.T) {
    t.Parallel()

    opts := &terragrunt.Options{
        TerragruntDir: "../examples/terragrunt-example",
    }

    defer terragrunt.DestroyContext(t, t.Context(), opts)
    terragrunt.ApplyContext(t, t.Context(), opts)

    output := terragrunt.OutputJSONContext(t, t.Context(), opts, "")
    require.NotEmpty(t, output)
}

After 2.0, you change the import path and the rest stays put:

import (
    "github.com/gruntwork-io/terratest/modules/terragrunt/v2"
)

Then run go mod tidy to drop the transitive dependencies the old monolithic module pulled in. Multi-package consumers do this once per imported module, but the per-module shape stays the same.

The reason we are making this change is that Terratest's surface area is expanding. Members of the community want to leverage Terratest for testing more than OpenTofu/Terraform and Terragrunt: cloud integration tests, Kubernetes, Helm, Docker, OPA, SSH, and DNS. IaC controls a large estate; the project should be able to grow with it without bloating long-time users.

You don't have to upgrade on day one. Stay on 1.0 as long as it serves you, and adopt 2.0 module-by-module when you need it.

Beyond 2.0

Future major releases of Terratest will happen rarely, but they will happen. Breaking changes have a place. Where possible, they land first as deprecation notices in an earlier release and then as removals later. The pattern looks like this:

// Deprecated: Use [DestroyContext] instead.
func Destroy(t testing.TestingT, options *Options) string {
    return DestroyContext(t, context.Background(), options)
}

The deprecated function continues to work; it delegates to the new version. You see the deprecation notice in your IDE and in godoc, giving you time to migrate before the old function is removed in a future major release.

Join the community

The Terratest community is deeply integrated with the Terragrunt community. The fastest growing part is the Terragrunt Discord server, where you can chat with maintainers, Terragrunt Ambassadors, and other Terratest users. Discussions specific to Terratest's broader surface (cloud integration testing, Kubernetes, Helm, OPA, and friends) are welcome there too.

If you are not already active, the upgrade to 1.0 is a great time to drop in. Issues, PRs, and feedback are welcome. Terratest 1.0 reflects work from a long list of community contributors, and we’re glad we can offer you the backwards compatibility guarantees expected from a major release.