Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/anaconda/terratest-helpers
Helpers for your terratest runs. Avoids duplicating code all the time.
https://github.com/anaconda/terratest-helpers
Last synced: about 2 months ago
JSON representation
Helpers for your terratest runs. Avoids duplicating code all the time.
- Host: GitHub
- URL: https://github.com/anaconda/terratest-helpers
- Owner: anaconda
- Created: 2022-08-24T10:17:13.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-04-04T07:36:22.000Z (10 months ago)
- Last Synced: 2024-04-04T08:37:48.583Z (10 months ago)
- Language: Go
- Size: 59.6 KB
- Stars: 0
- Watchers: 6
- Forks: 0
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# terratest-helpers
This module makes your terratest tests easier with pre-defined stages and other helpful functions.
All functions that init or apply the module allow you to specify an `errorFunc` which is called when the terraform command fails.
The error and the output of the terraform command are passed to that function so that you can define if the test should succeed or fail.
## Repository layout
To ensure correct function of this module, you need to:
- Put your tests in the directory `test`.
- Put variable files for your tests in `test/variables` and name them as the test is named
- Put provider configuration into the `test/provider.tf` file## Functions
### Run functions
Those functions are the easy start into testing, with more complex scenarios covered below. They are called “run functions” because their name starts with `Run`.
All run functions destroy the deployed infrastructure afterwards.
Run functions abstract [stages](#stages) for you.To only run some stages, set a `SKIP_$stage` environment variable to skip a certain stage, e.g. `SKIP_destroy`. This makes developing and debugging tests much easier.
For examples, see [the examples section](#examples).
Available run functions are:
- `RunNoValidate`: Run with default options and no extra validation
- `RunValidate`: Same as `RunNoValidate`, but with a validation function
- `RunOptionsNoValidate`: Run with configured terraform options, no extra validation
- `RunOptionsValidate`: Same as `RunOptionsNoValidate`, but with a validation functionIn a validation function, you can inspect the deployed infrastructure and have the test fail with `assert.Fail` if it does not match what you are expecting.
### Terraform Options
You can use the `DefaultOptions` function for default terraformOptions to be set automatically. Those are:
- `TerraformDir`, set to the absolute path of the module as the tests are in a subdirectory named `tests`
- `VarFiles` is appended the with the `.tfvars` file in `test/variables` that has the same as the running testUsing `DefaultOptions` ensures that the module directory is copied so that tests can be run in parallel with `t.Parallel()`
### Stages
:information_source: You need stages if you expect e.g. the `terraform plan` to fail for a test and want to validate the errors that occur, see the examples below.
Available stages are:
- `setup`: Saves the `terraformOptions`, runs `terraform init` and `terraform plan`. You can specify an `errorFunc` here.
- `apply`: Runs `terraform apply`. You can specify an `errorFunc` here.
- `validate`: If you want to check the state of the deployed infrastructure, you can do so in the validate stage. Pass a `validateFunc` into `StageValidate`.
- `destroy`: Runs `terraform destroy` and calls the `Cleanup` function.### Others
- `Cleanup`: Removes the test data directory `.test-data` and test provider configuration `test-provider.tf`.
## Examples
### Standard test
```go
func TestDefaults(t *testing.T) {
// If the test needs to run on its own, e.g. because
// of quota limitations, remove this line
t.Parallel()helpers.RunNoValidate(t)
}
```with this, the test will run the module with the variables in `test/variables/TestDefaults.tfvars` and expect all operations to be successful.
### Specifying dynamic variables
When you need to define not only constant variables, but also dynamic ones, you can use `RunOptionsNoValidate` as follows:
```go
func TestWithVars(t *testing.T) {
// If the test needs to run on its own, e.g. because
// of quota limitations, remove this line
t.Parallel()helpers.RunOptionsNoValidate(t, &terraform.Options{
Vars: map[string]interface{}{
"name": uuid.New(),
},
})
}
```This is needed for e.g. tests with S3 buckets to ensure every bucket is named uniquely.
### Expected to fail on apply
If a test is expected to fail on apply, defer the `destroy` stage and pass an error function to the `apply` stage:
```go
func TestS3BucketDefault(t *testing.T) {
t.Parallel()
terraformOptions := defaultOptions(t)// set everything up for the terraform apply later
terraformOptions.Vars = map[string]interface{}{
"name": uuid.New(),
}defer helpers.StageDestroy(t, terraformOptions.TerraformDir)
helpers.StageSetup(t, terraformOptions.TerraformDir, terraformOptions)
helpers.StageApply(t, terraformOptions.TerraformDir, func(err error, stdoutStderr string) {
// This error is expected
if err != nil {
if !strings.Contains(stdoutStderr, "Error: Some expected error") {
assert.Fail(t, "We expected an error, but it did not occur. Instead, another error was returned.")
}
}
})
}
```### Expected to fail on plan
For a test that is expected to fail on plan, use the `Cleanup` function.
```go
func TestS3BucketBackupOnVersioningOff(t *testing.T) {
t.Parallel()
terraformOptions := defaultOptions(t)terraformOptions.NoColor = true
terraformOptions.Vars = map[string]interface{}{
"name": uuid.New(),
"backup": "on",
"versioning": "Disabled",
}defer helpers.Cleanup(t, terraformOptions.TerraformDir)
// The terraform plan is expected to fail as versioning can't be turned off with backups turned on.
helpers.StageSetup(t, terraformOptions.TerraformDir, terraformOptions, func(err error, stdoutStderr string) {
// This error is expected, the precondition failed
if err != nil {
if !strings.Contains(stdoutStderr, "Error: Resource precondition failed") || !strings.Contains(stdoutStderr, "Versioning cannot be disabled when backups are enabled") {
assert.Fail(t, "The precondition checking versioning and backup configuration did not fail, but there is another error.")
}
} else {
// There must be an error in the precondition
assert.Fail(t, "There are no errors, but the precondition checking versioning and backup configuration must fail.")
}
})
}
```## Development
When cloning this repository, run `make init` locally. This sets up pre-commit, which takes care of the go formatting.
## Versioning
Versioning follows the go standard: Semantic versioning with a `v` prefix. Tags are currently created and pushed manually.