Skip to content

Commit

Permalink
docs: Update Check function examples with statecheck package impl…
Browse files Browse the repository at this point in the history
…ementations (#363)
  • Loading branch information
austinvalle authored Aug 6, 2024
1 parent f9ca4c3 commit 4910d52
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 144 deletions.
8 changes: 4 additions & 4 deletions website/docs/plugin/testing/acceptance-tests/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ or more configuration files, allowing multiple scenarios to be tested.

Terraform acceptance tests use real Terraform configurations to exercise the
code in real plan, apply, refresh, and destroy life cycles. When run from the
root of a Terraform Provider codebase, Terraforms testing framework compiles
root of a Terraform Provider codebase, Terraform's testing framework compiles
the current provider in-memory and executes the provided configuration in
developer defined steps, creating infrastructure along the way. At the
conclusion of all the steps, Terraform automatically destroys the
infrastructure. Its important to note that during development, its possible
infrastructure. It's important to note that during development, it's possible
for Terraform to leave orphaned or “dangling” resources behind, depending on the
correctness of the code in development. The testing framework provides means to
validate all resources are destroyed, alerting developers if any fail to
Expand All @@ -42,7 +42,7 @@ While the test framework provides a reasonable simulation of real-world usage, t

Terraform follows many of the Go programming language conventions with regards
to testing, with both acceptance tests and unit tests being placed in a file
that matches the file under test, with an added `_test.go` suffix. Heres an
that matches the file under test, with an added `_test.go` suffix. Here's an
example file structure:

```
Expand Down Expand Up @@ -302,6 +302,6 @@ This error indicates that the provider server could not connect to Terraform Cor
Terraform relies heavily on acceptance tests to ensure we keep our promise of
helping users safely and predictably create, change, and improve
infrastructure. In our next section we detail how to create “Test Cases”,
individual acceptance tests using Terraforms testing framework, in order to
individual acceptance tests using Terraform's testing framework, in order to
build and verify real infrastructure. [Proceed to Test
Cases](/terraform/plugin/testing/acceptance-tests/testcase)
38 changes: 19 additions & 19 deletions website/docs/plugin/testing/acceptance-tests/testcase.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ description: |-

Acceptance tests are expressed in terms of **Test Cases**, each using one or
more Terraform configurations designed to create a set of resources under test,
and then verify the actual infrastructure created. Terraforms `resource`
and then verify the actual infrastructure created. Terraform's `resource`
package offers a method `Test()`, accepting two parameters and acting as the
entry point to Terraforms acceptance test framework. The first parameter is the
standard [\*testing.T struct from Golangs Testing package][3], and the second is
entry point to Terraform's acceptance test framework. The first parameter is the
standard [\*testing.T struct from Golang's Testing package][3], and the second is
[TestCase][1], a Go struct that developers use to setup the acceptance tests.

Heres an example acceptance test. Here the Provider is named `Example`, and the
Here's an example acceptance test. Here the Provider is named `Example`, and the
Resource under test is `Widget`. The parts of this test are explained below the
example.

Expand All @@ -34,15 +34,15 @@ func TestAccExampleWidget_basic(t *testing.T) {
Steps: []resource.TestStep{
{
Config: testAccExampleResource(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleResourceExists("example_widget.foo", &widgetBefore),
),
ConfigStateChecks: []statecheck.StateCheck{
stateCheckExampleResourceExists("example_widget.foo", &widgetBefore),
},
},
{
Config: testAccExampleResource_removedPolicy(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleResourceExists("example_widget.foo", &widgetAfter),
),
ConfigStateChecks: []statecheck.StateCheck{
stateCheckExampleResourceExists("example_widget.foo", &widgetAfter),
},
},
},
})
Expand Down Expand Up @@ -81,7 +81,7 @@ func TestAccExampleWidget_basic(t *testing.T) {
The majority of acceptance tests will only invoke `resource.Test()` and exit. If
at any point this method encounters an error, either in executing the provided
Terraform configurations or subsequent developer defined checks, `Test()` will
invoke the `t.Error` method of Gos standard testing framework and the test will
invoke the `t.Error` method of Go's standard testing framework and the test will
fail. A failed test will not halt or otherwise interrupt any other tests
currently running.

Expand Down Expand Up @@ -190,7 +190,7 @@ a configuration file for testing must be represented in this map or the test
will fail during initialization.

This map is most commonly constructed once in a common `init()` method of the
Providers main test file, and includes an object of the current Provider type.
Provider's main test file, and includes an object of the current Provider type.

**Example usage:** (note the different files `widget_test.go` and `provider_test.go`)

Expand Down Expand Up @@ -326,15 +326,15 @@ func TestAccExampleWidget_basic(t *testing.T) {
Steps: []resource.TestStep{
{
Config: testAccExampleResource(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleResourceExists("example_widget.foo", &widgetBefore),
),
ConfigStateChecks: []statecheck.StateCheck{
stateCheckExampleResourceExists("example_widget.foo", &widgetBefore),
},
},
{
Config: testAccExampleResource_removedPolicy(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleResourceExists("example_widget.foo", &widgetAfter),
),
ConfigStateChecks: []statecheck.StateCheck{
stateCheckExampleResourceExists("example_widget.foo", &widgetAfter),
},
},
},
})
Expand All @@ -346,7 +346,7 @@ func TestAccExampleWidget_basic(t *testing.T) {
`TestCases` are used to verify the features of a given part of a plugin. Each
case should represent a scenario of normal usage of the plugin, from simple
creation to creating, adding, and removing specific properties. In the next
Section [`TestSteps`][2], well detail `Steps` portion of `TestCase` and see how
Section [`TestSteps`][2], we'll detail `Steps` portion of `TestCase` and see how
to create these scenarios by iterating on Terraform configurations.

[1]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/helper/resource#TestCase
Expand Down
58 changes: 36 additions & 22 deletions website/docs/plugin/testing/acceptance-tests/teststep.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -64,42 +64,59 @@ func TestAccExampleWidget_basic(t *testing.T) {
Steps: []resource.TestStep{
{
Config: testAccExampleResource(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleResourceExists("example_widget.foo", &widgetBefore),
),
ConfigStateChecks: []statecheck.StateCheck{
stateCheckExampleResourceExists("example_widget.foo", &widgetBefore),
},
},
{
Config: testAccExampleResource_removedPolicy(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleResourceExists("example_widget.foo", &widgetAfter),
),
ConfigStateChecks: []statecheck.StateCheck{
stateCheckExampleResourceExists("example_widget.foo", &widgetAfter),
},
},
},
})
}
```

In the above example each `TestCase` invokes a function to retrieve its desired
In the above example each `TestCase` invokes a function to retrieve it's desired
configuration, based on a randomized name provided, however an in-line string or
constant string would work as well, so long as they contain valid Terraform
configuration for the plugin or resource under test. This pattern of first
applying and checking a basic configuration, followed by applying a modified
configuration with updated or additional checks is a common pattern used to test
update functionality.

## State Check Functions
## Plan Checks
Before and after the configuration for a `TestStep` is applied, Terraform's testing framework provides developers an opportunity to make test assertions against `terraform plan` results via the plan file. This is provided via [Plan Checks](/terraform/plugin/testing/acceptance-tests/plan-checks), which provide both built-in plan checks and an interface to implement custom plan checks.

## State Checks

After the configuration for a `TestStep` is applied, Terraform's testing
framework provides developers an opportunity to check the results by providing one
or more [state check implementations](/terraform/plugin/testing/acceptance-tests/state-checks).
While possible to only supply a single state check, it is recommended you use multiple state checks
to validate specific information about the results of the `terraform apply` ran in each `TestStep`.

After the configuration for a `TestStep` is applied, Terraform’s testing
framework provides developers an opportunity to check the results by providing a
“Check” function. While possible to only supply a single function, it is
recommended you use multiple functions to validate specific information about
the results of the `terraform apply` ran in each `TestStep`. The `Check`
See the [State Checks](/terraform/plugin/testing/acceptance-tests/state-checks) section for more information about the built-in state checks for resources, data sources,
output values, and how to write custom state checks.

### Legacy Check function

<Note>

Use the new `ConfigStateChecks` attribute and [State Check implementations](/terraform/plugin/testing/acceptance-tests/state-checks)
instead of the `Check` function.

</Note>

The `Check` function is used to check results of a Terraform operation. The `Check`
attribute of `TestStep` is singular, so in order to include multiple checks
developers should use either `ComposeTestCheckFunc` or
`ComposeAggregateTestCheckFunc` (defined below) to group multiple check
functions, defined below:

### ComposeTestCheckFunc
#### ComposeTestCheckFunc

ComposeTestCheckFunc lets you compose multiple TestCheckFunc functions into a
single check. As a user testing their provider, this lets you decompose your
Expand All @@ -124,10 +141,10 @@ Steps: []resource.TestStep{
},
```

### ComposeAggregateTestCheckFunc
#### ComposeAggregateTestCheckFunc

ComposeAggregateTestCheckFunc lets you compose multiple TestCheckFunc functions
into a single check. Its purpose and usage is identical to
into a single check. It's purpose and usage is identical to
ComposeTestCheckFunc, however each check is ran in order even if a previous
check failed, collecting the errors returned from any checks and returning a
single aggregate error. The entire `TestCase` is still stopped, and Terraform
Expand All @@ -149,7 +166,7 @@ Steps: []resource.TestStep{
},
```

## Builtin check functions
#### Built-in check functions

Terraform has several TestCheckFunc functions built in for developers to use for
common checks, such as verifying the status and value of a specific attribute in
Expand Down Expand Up @@ -204,7 +221,7 @@ All of these functions also accept the below syntax in attribute keys to enable
| `.#` | Number of elements in list or set | `TestCheckResourceAttr("example_widget.foo", "some_list.#", "2")` |
| `.%` | Number of keys in map | `TestCheckResourceAttr("example_widget.foo", "some_map.%", "2")` |

## Custom check functions
### Custom check functions

The `Check` field of `TestStep` accepts any function of type
[TestCheckFunc](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/helper/resource#TestCheckFunc).
Expand Down Expand Up @@ -299,9 +316,6 @@ func testAccCheckExampleWidgetExists(resourceName string, widget *example.Widget
}
```

## Plan Checks
Before and after the configuration for a `TestStep` is applied, Terraform's testing framework provides developers an opportunity to make test assertions against `terraform plan` results via the plan file. This is provided via [Plan Checks](/terraform/plugin/testing/acceptance-tests/plan-checks), which provide both built-in plan checks and an interface to implement custom plan checks.

## Sweepers

Acceptance Testing is an essential approach to validating the implementation of a Terraform Provider. Using actual APIs to provision resources for testing can leave behind real infrastructure that costs money between tests. The reasons for these leaks can vary, regardless Terraform provides a mechanism known as [Sweepers](/terraform/plugin/testing/acceptance-tests/sweepers) to help keep the testing account clean.
Acceptance Testing is an essential approach to validating the implementation of a Terraform Provider. Using actual APIs to provision resources for testing can leave behind real infrastructure that costs money between tests. The reasons for these leaks can vary, regardless Terraform provides a mechanism known as [Sweepers](/terraform/plugin/testing/acceptance-tests/sweepers) to help keep the testing account clean.
2 changes: 1 addition & 1 deletion website/docs/plugin/testing/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ verified. Terraform includes a framework for constructing acceptance tests that
imitate the execution of one or more steps of applying one or more configuration
files, allowing multiple scenarios to be tested.

Its important to reiterate that acceptance tests in resources _create actual
It's important to reiterate that acceptance tests in resources _create actual
cloud infrastructure_, with possible expenses incurred, and are the
responsibility of the user running the tests. Creating real infrastructure in
tests verifies the described behavior of Terraform Plugins in real world use
Expand Down
Loading

0 comments on commit 4910d52

Please sign in to comment.