Skip to content

Commit

Permalink
Adding documentation for state checks and null known value check type (
Browse files Browse the repository at this point in the history
  • Loading branch information
bendbennett committed Jan 10, 2024
1 parent 7bc660c commit 483b364
Show file tree
Hide file tree
Showing 6 changed files with 365 additions and 0 deletions.
25 changes: 25 additions & 0 deletions website/data/plugin-testing-nav-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,27 @@
}
]
},
{
"title": "State Checks",
"routes": [
{
"title": "Overview",
"path": "acceptance-tests/state-checks"
},
{
"title": "Resource State Checks",
"path": "acceptance-tests/state-checks/resource"
},
{
"title": "Output State Checks",
"path": "acceptance-tests/state-checks/output"
},
{
"title": "Custom State Checks",
"path": "acceptance-tests/state-checks/custom"
}
]
},
{
"title": "Known Value Checks",
"routes": [
Expand Down Expand Up @@ -85,6 +106,10 @@
"title": "Number",
"path": "acceptance-tests/known-value-checks/number"
},
{
"title": "Null ",
"path": "acceptance-tests/known-value-checks/null"
},
{
"title": "Object",
"path": "acceptance-tests/known-value-checks/object"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
page_title: 'Plugin Development - Acceptance Testing: Known Values'
description: >-
Null Value Checks for use with Plan Checks or State Checks.
---

# Null Known Value Checks

The known value checks that are available for null values are:

* [NullValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/null#nullvalueexact-check)

## `NullValueExact` Check

The [NullValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullValueExact) check tests that a resource attribute, or output value has an exactly matching null value.

Example usage of [NullValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/state-checks/resource) state check.

```go
func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) {
t.Parallel()

r.Test(t, r.TestCase{
// Provider definition omitted.
Steps: []r.TestStep{
{
Config: `resource "test_resource" "one" {}`,
ConfigStateChecks: r.ConfigStateChecks{
statecheck.ExpectKnownValue(
"test_resource.one",
tfjsonpath.New("bool_attribute"),
knownvalue.NullValueExact(),
),
},
},
},
})
}
```
119 changes: 119 additions & 0 deletions website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
---
page_title: 'Plugin Development - Acceptance Testing: State Checks'
description: >-
State Checks are test assertions that can inspect state during a TestStep. Custom State Checks can be implemented.
---

# Custom State Checks

The package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) also provides the [`StateCheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck) interface, which can be implemented for a custom state check.

The [`statecheck.CheckStateRequest`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#CheckStateRequest) contains the current state file, parsed by the [terraform-json package](https://pkg.go.dev/github.com/hashicorp/terraform-json#State).

Here is an example implementation of a state check that asserts that a specific resource attribute has a known type and value:

```go
package example_test

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-testing/statecheck"
)

var _ StateCheck = expectKnownValue{}

type expectKnownValue struct {
resourceAddress string
attributePath tfjsonpath.Path
knownValue knownvalue.Check
}

func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) {
var rc *tfjson.StateResource

if req.State == nil {
resp.Error = fmt.Errorf("state is nil")
}

if req.State.Values == nil {
resp.Error = fmt.Errorf("state does not contain any state values")
}

if req.State.Values.RootModule == nil {
resp.Error = fmt.Errorf("state does not contain a root module")
}

for _, resourceChange := range req.State.Values.RootModule.Resources {
if e.resourceAddress == resourceChange.Address {
rc = resourceChange

break
}
}

if rc == nil {
resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress)

return
}

result, err := tfjsonpath.Traverse(rc.AttributeValues, e.attributePath)

if err != nil {
resp.Error = err

return
}

if err := e.knownValue.CheckValue(result); err != nil {
resp.Error = err
}
}

func ExpectKnownValue(resourceAddress string, attributePath tfjsonpath.Path, knownValue knownvalue.Check) StateCheck {
return expectKnownValue{
resourceAddress: resourceAddress,
attributePath: attributePath,
knownValue: knownValue,
}
}
```

And example usage:
```go
package example_test

import (
"testing"

r "github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)

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

r.Test(t, r.TestCase{
// Provider definition omitted.
Steps: []r.TestStep{
{
Config: `resource "test_resource" "one" {
bool_attribute = true
}
`,
ConfigStateChecks: r.ConfigStateChecks{
statecheck.ExpectKnownValue(
"test_resource.one",
tfjsonpath.New("bool_attribute"),
knownvalue.BoolValueExact(true),
),
},
},
},
})
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
page_title: 'Plugin Development - Acceptance Testing: State Checks'
description: >-
State Checks are test assertions that can inspect state during a TestStep. The testing module
provides built-in State Checks for common use-cases, and custom State Checks can also be implemented.
---

# State Checks

During the **Lifecycle (config)** [mode](/terraform/plugin/testing/acceptance-tests/teststep#test-modes) of a `TestStep`, the testing framework will run `terraform apply`.

The execution of `terraform apply` results in a [state file](/terraform/language/state), and can be represented by this [JSON format](/terraform/internals/json-format#state-representation).

A **state check** is a test assertion that inspects the state file. Multiple state checks can be run, all assertion errors returned are aggregated, reported as a test failure, and all test cleanup logic is executed.

Refer to:

- [Resource State Checks](/terraform/plugin/testing/acceptance-tests/state-checks/resource) for built-in managed resource and data source state checks.
- [Output State Checks](/terraform/plugin/testing/acceptance-tests/state-checks/output) for built-in output-related state checks.
- [Custom State Checks](/terraform/plugin/testing/acceptance-tests/state-checks/custom) for defining bespoke state checks.
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
page_title: 'Plugin Development - Acceptance Testing: State Checks'
description: >-
State Checks are test assertions that can inspect state during a TestStep. The testing module
provides built-in Output Value State Checks for common use-cases.
---

# Output State Checks

The `terraform-plugin-testing` module provides a package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) with built-in output value state checks for common use-cases:

| Check | Description |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
| [`statecheck.ExpectKnownOutputValue(address, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue) | Asserts the output at the specified address has the specified type, and value. |
| [`statecheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath) | Asserts the output at the specified address, and path has the specified type, and value. |

## Example using `statecheck.ExpectKnownOutputValue`

The [`statecheck.ExpectKnownOutputValue(address, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue) state check verifies that a specific output value has a known type, and value.

Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownOutputValue` state check.

```go
func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) {
t.Parallel()

r.Test(t, r.TestCase{
// Provider definition omitted.
Steps: []r.TestStep{
{
Config: `resource "test_resource" "one" {
bool_attribute = true
}
output bool_output {
value = test_resource.one.bool_attribute
}
`,
ConfigStateChecks: r.ConfigStateChecks{
statecheck.ExpectKnownOutputValue(
"bool_output",
knownvalue.BoolValueExact(true),
),
},
},
},
})
}
```

## Example using `statecheck.ExpectKnownOutputValueAtPath`

The [`statecheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath) state check verifies that a specific output value at a defined path has a known type, and value.

Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownOutputValueAtPath` state check.

```go
func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) {
t.Parallel()

r.Test(t, r.TestCase{
// Provider definition omitted.
Steps: []r.TestStep{
{
Config: `resource "test_resource" "one" {
bool_attribute = true
}
output test_resource_one_output {
value = test_resource.one
}
`,
ConfigStateChecks: r.ConfigStateChecks{
statecheck.ExpectKnownOutputValueAtPath(
"test_resource_one_output",
tfjsonpath.New("bool_attribute"),
knownvalue.BoolValueExact(true),
),
},
},
},
})
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
page_title: 'Plugin Development - Acceptance Testing: State Checks'
description: >-
State Checks are test assertions that can inspect state during a TestStep. The testing module
provides built-in Managed Resource and Data Source State Checks for common use-cases.
---

# Resource State Checks

The `terraform-plugin-testing` module provides a package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) with built-in managed resource, and data source state checks for common use-cases:

| Check | Description |
|------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|
| [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. |
| [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. |

## Example using `statecheck.ExpectKnownValue`

The [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) state check provides a basis for asserting that a specific resource attribute has a known type, and value.

Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownValue` state check.

```go
func TestExpectKnownValue_CheckState_Bool(t *testing.T) {
t.Parallel()

r.Test(t, r.TestCase{
// Provider definition omitted.
Steps: []r.TestStep{
{
Config: `resource "test_resource" "one" {
bool_attribute = true
}
`,
ConfigStateChecks: r.ConfigStateChecks{
statecheck.ExpectKnownValue(
"test_resource.one",
tfjsonpath.New("bool_attribute"),
knownvalue.BoolValueExact(true),
),
},
},
},
})
}
```

## Example using `statecheck.ExpectSensitiveValue`

The [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) state check provides a basis for asserting that a specific resource attribute is marked as sensitive.

-> **Note:** In this example, a [TerraformVersionCheck](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/tfversion#TerraformVersionCheck) is being used to prevent execution of this test prior to Terraform version `1.4.6` (refer to the release notes for Terraform [v1.4.6](https://github.com/hashicorp/terraform/releases/tag/v1.4.6)).

```go
func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) {
t.Parallel()

r.UnitTest(t, r.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues
},
// Provider definition omitted.
Steps: []r.TestStep{
{
Config: `
resource "test_resource" "one" {
sensitive_string_attribute = "test"
}
`,
ConfigStateChecks: r.ConfigStateChecks{
statecheck.ExpectSensitiveValue("test_resource.one",
tfjsonpath.New("sensitive_string_attribute")),
},
},
},
})
}
```

0 comments on commit 483b364

Please sign in to comment.