Schema Coverage (Terraform resource vs acceptance tests)
Goal
Given a Terraform resource, compare its schema attributes/blocks to what the acceptance tests configure and assert, then highlight opportunities to improve coverage.
Report findings in this order:
- Attributes with no coverage
- Attributes with poor coverage
Inputs (infer if not provided)
- Resource name (e.g.
elasticstack_elasticsearch_security_api_key)
- Or the schema file / acceptance test file path
- Or the Go package directory containing the resource and
*_acc_test.go
If the user has an acceptance test open, infer the resource under test from:
resource.Test(...) names like resourceName := "elasticstack_..."
resource.ParallelTest(...) steps referencing a single resource
- config builder function names like
testAcc...Resource...
Workflow
1) Locate and parse the schema
Find the resource schema definition and capture all schema keys:
- Top-level attributes in
Schema: map[string]*schema.Schema{ ... }
- Nested block schemas in:
Elem: &schema.Resource{ Schema: ... }
- lists/sets/maps of resources and objects
- nested blocks referenced via helpers
For each attribute/block, record:
- Path: terraform attribute path (top-level
foo, nested block.0.bar, etc.)
- Schema metadata:
Required/Optional/Computed, ForceNew, type (TypeString, TypeList, etc.), MaxItems/MinItems
2) Locate acceptance tests and collect attribute usage
Scan the acceptance tests for two independent signals:
- Configured attributes: attributes explicitly set in HCL test configs (including nested blocks).
- Asserted attributes: attributes referenced in checks, including:
- value assertions (e.g.
TestCheckResourceAttr)
- set-only assertions (e.g.
TestCheckResourceAttrSet)
- absence assertions (e.g.
TestCheckNoResourceAttr)
- collection assertions (e.g. type-set element checks, list length checks)
Also detect update coverage by identifying multiple resource.TestStep{ Config: ... } steps for the same resource and whether attribute values change between steps.
3) Build a coverage matrix
For each schema attribute path, compute:
- Configured? (ever set in any test config)
- Asserted? (ever referenced by any check)
- Assertion quality:
- value-specific: asserts the exact value (preferred)
- set-only: only checks “is set” (weaker)
- absence: checks unset / removed (good for optional fields)
- Value diversity: count distinct values across steps/configs (e.g.
name="a" vs name="b")
- Optional-unset coverage: optional field has a test step where it is deliberately omitted, plus an assertion that it is absent (or defaults appropriately)
- Empty-collection coverage: collection has a step where it is empty (or omitted if optional), plus assertions validating the empty state
- Update coverage: attribute value changes across steps, and a post-update assertion verifies the new value
4) Produce the report (strict ordering)
Use the template below.
Report template
## Schema coverage report: <resource>
### Scope
- **Schema**: <file(s) or function(s)>
- **Acceptance tests**: <test file(s)>
### 1) Attributes with no coverage
These schema attributes/blocks are not referenced in acceptance tests (neither configured nor asserted):
- `<attr_path>`: <Required/Optional/Computed>, <type>. **Gap**: not configured, not asserted.
### 2) Attributes with poor coverage
These attributes appear in tests but the coverage is weak:
- `<attr_path>`: <schema flags/type>
- **Observed**: <how it’s currently used (configured/asserted), example values>
- **Gaps**:
- <one or more of: set-only assertion, single value only, no unset coverage, no empty collection coverage, no update coverage>
- **Suggested improvements**:
- <concrete test step or assertion to add>
### Suggested next steps (smallest diffs first)
1. Add value-specific assertions for set-only checks
2. Add an “unset optional” step + `TestCheckNoResourceAttr`
3. Add an “empty collection” step + collection assertions
4. Add an “update” step changing the attribute + post-update assertions
Rules of thumb (for prioritization)
- Prefer value-specific assertions over “is set”.
- For Optional attributes, include at least one step where the attribute is omitted, and assert absence/default behavior.
- For collections (list/set/map), add a case for empty (or omitted if optional), and assert the expected empty state.
- For Update behavior, ensure there is at least one multi-step test where the attribute changes and the test asserts the new state.
- For Computed-only attributes, it’s acceptable to use set-only assertions when exact values are not deterministic, but prefer deterministic assertions when possible.
Notes / limitations
- Some schemas are built via helpers; follow helper references until all attribute keys are accounted for.
- Attribute paths in checks often use
block.0.attr indexing; normalize consistently when matching to schema blocks.
- Don’t mark an attribute as “covered” solely because it appears in raw HCL—prefer it being asserted. Treat “configured but never asserted” as poor coverage, not good coverage.
1---2name: schema-coverage3description: Analyzes a Terraform resource schema and compares it to attributes used in the acceptance test suite (configs + assertions). Produces a prioritized report of missing and poor coverage (set-only assertions, single-value coverage, missing unset/empty cases, missing update coverage). Use when the user asks about schema coverage, test coverage gaps, or improving Terraform acceptance tests for a resource.4---56# Schema Coverage (Terraform resource vs acceptance tests)78## Goal910Given a Terraform resource, compare its **schema attributes/blocks** to what the acceptance tests **configure** and **assert**, then highlight opportunities to improve coverage.1112Report findings in this order:131. **Attributes with no coverage**142. **Attributes with poor coverage**1516## Inputs (infer if not provided)1718- Resource name (e.g. `elasticstack_elasticsearch_security_api_key`)19- Or the schema file / acceptance test file path20- Or the Go package directory containing the resource and `*_acc_test.go`2122If the user has an acceptance test open, infer the resource under test from:23- `resource.Test(...)` names like `resourceName := "elasticstack_..."`24- `resource.ParallelTest(...)` steps referencing a single resource25- config builder function names like `testAcc...Resource...`2627## Workflow2829### 1) Locate and parse the schema3031Find the resource schema definition and capture **all schema keys**:32- Top-level attributes in `Schema: map[string]*schema.Schema{ ... }`33- Nested block schemas in:34 - `Elem: &schema.Resource{ Schema: ... }`35 - lists/sets/maps of resources and objects36 - nested blocks referenced via helpers3738For each attribute/block, record:39- **Path**: terraform attribute path (top-level `foo`, nested `block.0.bar`, etc.)40- **Schema metadata**: `Required`/`Optional`/`Computed`, `ForceNew`, type (`TypeString`, `TypeList`, etc.), `MaxItems/MinItems`4142### 2) Locate acceptance tests and collect attribute usage4344Scan the acceptance tests for two independent signals:4546- **Configured attributes**: attributes explicitly set in HCL test configs (including nested blocks).47- **Asserted attributes**: attributes referenced in checks, including:48 - value assertions (e.g. `TestCheckResourceAttr`)49 - set-only assertions (e.g. `TestCheckResourceAttrSet`)50 - absence assertions (e.g. `TestCheckNoResourceAttr`)51 - collection assertions (e.g. type-set element checks, list length checks)5253Also detect **update coverage** by identifying multiple `resource.TestStep{ Config: ... }` steps for the same resource and whether attribute values change between steps.5455### 3) Build a coverage matrix5657For each schema attribute path, compute:58- **Configured?** (ever set in any test config)59- **Asserted?** (ever referenced by any check)60- **Assertion quality**:61 - **value-specific**: asserts the exact value (preferred)62 - **set-only**: only checks “is set” (weaker)63 - **absence**: checks unset / removed (good for optional fields)64- **Value diversity**: count distinct values across steps/configs (e.g. `name="a"` vs `name="b"`)65- **Optional-unset coverage**: optional field has a test step where it is deliberately omitted, plus an assertion that it is absent (or defaults appropriately)66- **Empty-collection coverage**: collection has a step where it is empty (or omitted if optional), plus assertions validating the empty state67- **Update coverage**: attribute value changes across steps, and a post-update assertion verifies the new value6869### 4) Produce the report (strict ordering)7071Use the template below.7273## Report template7475```markdown76## Schema coverage report: <resource>7778### Scope79- **Schema**: <file(s) or function(s)>80- **Acceptance tests**: <test file(s)>8182### 1) Attributes with no coverage83These schema attributes/blocks are not referenced in acceptance tests (neither configured nor asserted):84- `<attr_path>`: <Required/Optional/Computed>, <type>. **Gap**: not configured, not asserted.8586### 2) Attributes with poor coverage87These attributes appear in tests but the coverage is weak:88- `<attr_path>`: <schema flags/type>89 - **Observed**: <how it’s currently used (configured/asserted), example values>90 - **Gaps**:91 - <one or more of: set-only assertion, single value only, no unset coverage, no empty collection coverage, no update coverage>92 - **Suggested improvements**:93 - <concrete test step or assertion to add>9495### Suggested next steps (smallest diffs first)961. Add value-specific assertions for set-only checks972. Add an “unset optional” step + `TestCheckNoResourceAttr`983. Add an “empty collection” step + collection assertions994. Add an “update” step changing the attribute + post-update assertions100```101102## Rules of thumb (for prioritization)103104- Prefer **value-specific assertions** over “is set”.105- For **Optional** attributes, include at least one step where the attribute is **omitted**, and assert absence/default behavior.106- For **collections** (list/set/map), add a case for **empty** (or omitted if optional), and assert the expected empty state.107- For **Update** behavior, ensure there is at least one multi-step test where the attribute changes and the test asserts the new state.108- For **Computed-only** attributes, it’s acceptable to use set-only assertions when exact values are not deterministic, but prefer deterministic assertions when possible.109110## Notes / limitations111112- Some schemas are built via helpers; follow helper references until all attribute keys are accounted for.113- Attribute paths in checks often use `block.0.attr` indexing; normalize consistently when matching to schema blocks.114- Don’t mark an attribute as “covered” solely because it appears in raw HCL—prefer it being **asserted**. Treat “configured but never asserted” as poor coverage, not good coverage.