provider-test-patterns

Terraform provider acceptance test patterns using terraform-plugin-testing with the Plugin Framework. Covers test structure, TestCase/TestStep fields, ConfigStateChecks with custom statecheck.StateCheck implementations, plan checks, CompareValue for cross-step assertions, config helpers, import test

By hashicorp · 2,863 installs

npx skills add hashicorp/agent-skills --skill provider-test-patterns

Source repository · Upstream listing

Provider Acceptance Test Patterns Patterns for writing acceptance tests using [terraform plugin testing](https://github.com/hashicorp/terraform plugin testing) with the [Plugin Framework](https://github.com/hashicorp/terraform plugin framework). Source: [HashiCorp Testing Patterns](https://developer.hashicorp.com/terraform/plugin/testing/testing patterns) References (load when needed): references/checks.md — statecheck, plancheck, knownvalue types, tfjsonpath, comparers references/sweepers.md — sweeper setup, TestMain, dependencies references/ephemeral.md — ephemeral resource testing, echoprovider, multi step patterns Test Lifecycle The framework runs each TestStep through: plan → apply → refresh → final plan . If the final plan shows a diff, the test fails (unless ExpectNonEmptyPlan is set). After all steps, destroy runs followed by CheckDestroy . This means every test automatically verifies that configurations apply cleanly and produce no drift — no assertions needed for that. Test Function Structure Use resource.ParallelTest by default. Use resource.Test only when tests share state or cannot run concurrently. Provider Factory TestCase Fields Field Purpose PreCheck func() — verify prerequisites (env vars, API access) ProtoV6ProviderFactories Plugin Framework provider factories CheckDestroy TestCheckFunc — verify resources destroyed after all steps Steps []TestStep — sequential test operations TerraformVersionChecks []tfversion.TerraformVersionCheck — gate by CLI version TestStep Fields Config Mode Field Purpose Config Inline HCL string to apply ConfigStateChecks []statecheck.StateCheck — modern assertions (preferred) ConfigPlanChecks resource.ConfigPlanChecks{PreApply: []plancheck.PlanCheck{...}} ExpectError regexp.Regexp — expect failure matching pattern ExpectNonEmptyPlan bool — expect non empty plan after apply PlanOnly bool — plan without applying Destroy bool — run destroy step PreConfig func() — setup before step Import Mode Field Purpose ImportState true to enable import mode ImportStateVerify Verify imported state matches prior state ImportStateVerifyIgnore []string — attributes to skip during verify ImportStateKind resource.ImportBlockWithID — import block generation ResourceName Resource address to import ImportStateId Override the ID used for import Check Functions Modern: ConfigStateChecks (preferred) Type safe with aggregated error reporting. Compose built in checks with custom statecheck.StateCheck implementations. See references/checks.md for full knownvalue types, tfjsonpath navigation, and comparers. Do not mix Check (legacy) and ConfigStateChecks in the same step. Legacy: Check (for CheckDestroy and migration) CheckDestroy on TestCase requires TestCheckFunc . The Check field on TestStep also accepts TestCheckFunc but prefer ConfigStateChecks for new tests. ComposeAggregateTestCheckFunc reports all errors; ComposeTestCheckFunc fails fast on the first. Config Helpers Use numbered format verbs — %[1]q for quoted strings, %[1]s for raw: Scenario Patterns Basic + Update (combine in one test — updates are supersets of basic) Import After a config step, verify import produces identical state. Use ImportStateKind for import block generation: Disappears (resource deleted externally) Validation (expect error) Regression (two commit workflow) A proper bug fix uses at least two commits: first commit the regression test (which fails, confirming the bug), then commit the fix (test passes). This lets reviewers independently verify the test reproduces the issue by checking out the first commit, then advancing to the fix. Name and document regression tests to identify the issue they fix. Include a link to the original bug report when possible. Helper Functions Custom StateCheck: Exists Implement statecheck.StateCheck for API existence verification. Separate the exists check into its own function for reuse across steps — the source recommends this as a design principle: Custom StateCheck: Disappears Delete a resource via API to simulate external deletion: State Resource Lookup (shared utility) Destroy Check (TestCheckFunc — required by CheckDestroy) PreCheck