.agents/skills/review-tests-helpers/SKILL.md
Assume the @maintainer persona. Scope: Exists/Destroy helpers, data source tests, list resource tests, unit tests. See review-tests for per-resource basics. Loaded from review-pr.
testAccCheck<Resource>Exists should:
s.RootModule().Resources[name].rs.Primary.ID != "".acctest.ProviderMeta(ctx, t).<Service>Client(ctx) for the client — never construct a fresh client.tf<svc>.Find<Name>ByID(ctx, conn, ...).testAccCheck<Resource>Destroy should:
rs.Type != "aws_<svc>_<thing>".retry.NotFound(err) as success (return nil).errs.IsA[*awstypes.<NotFoundException>] rather than type assertions if it inspects errors directly.Wrap real failures with create.Error(names.<Service>, create.ErrActionCheckingExistence|ErrActionCheckingDestroyed, tf<svc>.ResName<Name>, id, err) rather than fmt.Errorf / errors.New.
Test files reach into the package via a sibling exports_test.go:
package <svc>
var (
Resource<Name> = new<Name>Resource // Framework
// or: Resource<Name> = resource<Name> // SDKv2
Find<Name>ByID = find<Name>ByID
)
Flag PRs that export production identifiers (capitalize the real find<Name>ByID) instead of using exports_test.go, or reach into the package via build tags or internal/ traversal hacks. The package is imported in tests as tf<svc> "github.com/hashicorp/terraform-provider-aws/internal/service/<svc>".
Data source tests follow the resource conventions with these differences:
dataSourceName := "data.aws_<svc>_<thing>.test".resource.TestCheckResourceAttrPair(dataSourceName, attr, resourceName, attr) over hard-coded values when the data source mirrors a resource._disappears test.CheckDestroy is still required when the test creates a backing resource.List resources require three scenarios for parity:
_List_basic — basic listing._List_includeResource — with include_resource = true and full attribute checks._List_regionOverride — region override; requires acctest.PreCheckMultipleRegion(t, 2).List resource tests use static testdata, not inline configs:
ConfigDirectory: config.StaticDirectory("testdata/<Resource>/list_<scenario>/"),
ConfigVariables: config.Variables{ acctest.CtRName: config.StringVariable(rName), ... },
A separate Step with Query: true exercises the list operation. Identity assertions use tfstatecheck.Identity() / identity.GetIdentity(resourceName) and the tfquerycheck.* helpers under internal/acctest/querycheck.
List resource tests also require a Terraform version floor (currently 1.14):
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_14_0),
},
Unit tests are for logic that doesn't touch AWS — parsers, custom flatteners/expanders, ID composition, validators. They:
t.Parallel() at top and inside subtests).t.Run(tc.TestName, ...).acctest.Context, acctest.PreCheck, or instantiate an AWS client.Flag unit tests added for trivial pass-through flatteners/expanders — they're noise. Flag acceptance-style tests mis-named without the TestAcc prefix.