Skip to content

Commit

Permalink
Add Option to use Terraform Configuration in TestStep (#153)
Browse files Browse the repository at this point in the history
* Adding ConfigDirectory to TestStep (#150)

* Add teststep.Config interface so that logic that examines the contents of TestStep.Config or TestStep.Directory can be encapsulated in teststep.config struct (#150)

* Update TestStep.Validate() to use teststep.Config interface implementation (#150)

* Switching to using a teststep.ConfigurationRequest struct for use in instantiating implementations of teststep.Config (#150)

* Refactoring to use type implementing teststep.Config interface (#150)

* Refactoring testStepNewImportState() to use type implementing teststep.Config interface for applied configuration (#150)

* Switching to using type implementing teststep.Config interface (#150)

* Moved TestStep.configHasProviderBlock(), TestStep.configHasTerraformBlock and TestStep.mergedConfig() to configuration.HasProviderBlock(), configuration.hasTerraformBlock and configuration.MergedConfig(), respectively (#150)

* Fix validation error message to include ConfigDirectory (#150)

* Added testCaseProviderConfig and testStepProviderConfig as fields on configuration struct to simplify processing during GetRaw() and the equivalent function(s) for processing Directory and File (#150)

* Add initial implementation of copying files from ConfigDirectory into wd.baseDir (#150)

* Switch to using WriteDirectory() method on configuration to make management of writing test case provider config or test step provider config simpler when handling copying of files from configuration.directory (#150)

* Adding tests to verify that the ExternalProviders specified in a TestCase or TestStep are being used when TestStep.ConfigDirectory is specified (#150)

* Extending implementation of HasProviderBlock() to include detection of provider blocks in configuration files within the configuration directory (#150)

* Moving writing of raw config or copy of config directory files internally to configuration struct. (#150)

* Removing writing of configuration files for external providers (contained within testCaseProviderConfig and testStepProvider config fields) when processing config directory as the expectation is that external providers will be specified directly in the terraform configuration files within the config directory (#150)

* Adding HasConfigurationFiles() func to Config interface to be able to validate that when ConfigDirectory is defined that ExternalProviders cannot be specified for either TestCase or TestStep (#150)

* Reinstating TestStep.mergedConfig() method as terraform and provider blocks are only written when using TestStep.Config. The expectation is that when using TestStep.ConfigDirectoy, the terraform files within the configuration directory will specify the terraform and/or provider blocks as necessary (#150)

* Adding a couple of tests to verify behaviour when using multiple terraform configuration files in TestStep.ConfigDirectory (#150)

* Switching to using TestStepConfigFunc type for TestStep.ConfigDirectory (#150)

* Adding acceptance test coverage for StaticDirectory(), TestNameDirectory() and TestStepDirectory() (#150)

* Adding Exec() method to TestStepConfigFunc type and removing ExecuteTestStepConfigFunc (#150)

* Adding ConfigVariables to allow defining of Terraform variables within a TestStep (#150)

* Adding docs for config directory and variables (#150)

* Adding tests for TestStepConfigFunc.Exec() method (#150)

* Adding tests for config<Type>Variable and Variables.Write() func (#150)

* Adding copyright headers (#150)

* Unmarshalling before comparing (#150)

* Apply suggestions from code review

Co-authored-by: Brian Flad <bflad417@gmail.com>

* Adding TestName to TestStepConfigRequest and updating TestStepDirectory() func to use TestName (#150)

* Switching to supplying t.Name() to TestStepConfigRequest (#150)

  * Moving all test fixtures for ConfigDirectory to resource/testdata

* Marshalling Variables directly (#150)

* Adding comment to explain the usage of Unwrap() (#150)

* Adding FloatVariable and IntegerVariable and removing NumberVariable (#150)

* Changing ConfigurationRequest fields Directory and Raw to *string to make it clear that they are optional (#150)

* Adding Validate() func to ConfigurationRequest along with test coverage (#150)

* Adding configurationDirectory and configurationString types (#150)

  * Configuration() now returns the Config interface to accommodate the different types that could be returned (e.g., configurationDirectory, configurationString)

* Renaming raw.go to string.go to match type defined therein (#150)

* Adding support for TestStep.ConfigFile field (#150)

* Updating docs for config pkg (#150)

* Adding documentation into teststep/config.go and tests for exported methods/funcs in teststep/config.go (#150)

  * Includes refactoring of Configuration func to remove error returned as this was always nil and the returned Config interface needs to be checked for nil in any case.

* Adding checks for absolute filepath in configurationDirectory and configurationFile HasProviderBlock, HasTerraformBlock and Write methods (#150)

  * Adding test coverage for configurationDirectory and configurationFile HasProviderBlock method

* Adding tests configurationDirectory, configurationFile and configurationString HasTerraformBlock methods (#150)

* Adding test coverage for error conditions and configurationDirectory, configurationFile and configurationString Write methods (#150)

* Adding empty dir for tests to git (#150)

* Adding a page on usage of Terraform configuration to the website docs (#150)

* Adding changelog entries (#150)

* Adding test to demonstrate that the TestStep number is being used dynamically to determine the directory containing the Terraform configuration (#150)

* Removing unneeded elsif conditional (#150)

* Updating docs (#150)

* Removing any configuration or variables files from previous test steps prior to copy configuration and variables for current test step (#150)

* Updating docs (#150)

* Apply suggestions from code review

Co-authored-by: Brian Flad <bflad417@gmail.com>

* Update .changes/unreleased/FEATURES-20230728-152822.yaml

Co-authored-by: Brian Flad <bflad417@gmail.com>

* Removing unneeded changelog entries (#150)

* Reusing stepNumber variable (#150)

---------

Co-authored-by: Brian Flad <bflad417@gmail.com>
  • Loading branch information
bendbennett and bflad committed Aug 31, 2023
1 parent 5eb089d commit e46c64f
Show file tree
Hide file tree
Showing 144 changed files with 6,262 additions and 209 deletions.
6 changes: 6 additions & 0 deletions .changes/unreleased/FEATURES-20230728-143814.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: FEATURES
body: 'config: Introduced new `config` package which contains interfaces and helper
functions for working with native Terraform configuration and variables'
time: 2023-07-28T14:38:14.006499+01:00
custom:
Issue: "153"
6 changes: 6 additions & 0 deletions .changes/unreleased/FEATURES-20230728-152737.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: FEATURES
body: 'helper/resource: Added `TestStep.ConfigDirectory` to allow specifying a directory
containing Terraform configuration for use during acceptance tests'
time: 2023-07-28T15:27:37.944964+01:00
custom:
Issue: "153"
6 changes: 6 additions & 0 deletions .changes/unreleased/FEATURES-20230728-152822.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: FEATURES
body: 'helper/resource: Added `TestStep.ConfigFile` to allow specifying a file containing
Terraform configuration for use during acceptance tests'
time: 2023-07-28T15:28:22.204411+01:00
custom:
Issue: "153"
6 changes: 6 additions & 0 deletions .changes/unreleased/FEATURES-20230728-152917.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: FEATURES
body: 'helper/resource: Added `TestStep.ConfigVariables` to allow specifying Terraform variables
for use with Terraform configuration during acceptance tests'
time: 2023-07-28T15:29:17.02183+01:00
custom:
Issue: "153"
38 changes: 38 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package config

// TestStepConfigFunc is the callback type used with acceptance tests to
// specify a string which either identifies a directory containing
// Terraform configuration files, or a file that contains Terraform
// configuration.
type TestStepConfigFunc func(TestStepConfigRequest) string

// TestStepConfigRequest defines the request supplied to types
// implementing TestStepConfigFunc. StepNumber is one-based
// and is used in the predefined helper functions:
//
// - [config.TestStepDirectory]
// - [config.TestStepFile].
//
// TestName is used in the predefined helper functions:
//
// - [config.TestNameDirectory]
// - [config.TestStepDirectory]
// - [config.TestNameFile]
// - [config.TestStepFile]
type TestStepConfigRequest struct {
StepNumber int
TestName string
}

// Exec executes TestStepConfigFunc if it is not nil, otherwise an
// empty string is returned.
func (f TestStepConfigFunc) Exec(req TestStepConfigRequest) string {
if f != nil {
return f(req)
}

return ""
}
63 changes: 63 additions & 0 deletions config/directory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package config

import (
"path/filepath"
"strconv"
)

// StaticDirectory returns the supplied directory.
func StaticDirectory(directory string) func(TestStepConfigRequest) string {
return func(_ TestStepConfigRequest) string {
return directory
}
}

// TestNameDirectory returns the name of the test prefixed with
// "testdata".
//
// For example, given test code:
//
// func TestExampleCloudThing_basic(t *testing.T) {
// resource.Test(t, resource.TestCase{
// Steps: []resource.TestStep{
// {
// ConfigDirectory: config.TestNameDirectory(),
// },
// },
// })
// }
//
// The testing configurations will be expected in the
// testdata/TestExampleCloudThing_basic/ directory.
func TestNameDirectory() func(TestStepConfigRequest) string {
return func(req TestStepConfigRequest) string {
return filepath.Join("testdata", req.TestName)
}
}

// TestStepDirectory returns the name of the test suffixed with the
// test step number and prefixed with "testdata".
//
// For example, given test code:
//
// func TestExampleCloudThing_basic(t *testing.T) {
// resource.Test(t, resource.TestCase{
// Steps: []resource.TestStep{
// {
// ConfigDirectory: config.TestStepDirectory(),
// },
// },
// })
// }
//
// The testing configurations will be expected in the
// testdata/TestExampleCloudThing_basic/1 directory as
// TestStepConfigRequest.StepNumber is one-based.
func TestStepDirectory() func(TestStepConfigRequest) string {
return func(req TestStepConfigRequest) string {
return filepath.Join("testdata", req.TestName, strconv.Itoa(req.StepNumber))
}
}
54 changes: 54 additions & 0 deletions config/directory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package config_test

import (
"testing"

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

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

testCases := map[string]struct {
testStepConfigFunc config.TestStepConfigFunc
testStepConfigRequest config.TestStepConfigRequest
expected string
}{
"static_directory": {
testStepConfigFunc: config.StaticDirectory("name_of_directory"),
expected: "name_of_directory",
},
"test_name_directory": {
testStepConfigFunc: config.TestNameDirectory(),
testStepConfigRequest: config.TestStepConfigRequest{
TestName: "TestTestStepConfigFunc_Exec",
},
expected: "testdata/TestTestStepConfigFunc_Exec",
},
"test_step_directory": {
testStepConfigFunc: config.TestStepDirectory(),
testStepConfigRequest: config.TestStepConfigRequest{
StepNumber: 1,
TestName: "TestTestStepConfigFunc_Exec",
},
expected: "testdata/TestTestStepConfigFunc_Exec/1",
},
}

for name, testCase := range testCases {
name, testCase := name, testCase

t.Run(name, func(t *testing.T) {
t.Parallel()

got := testCase.testStepConfigFunc.Exec(testCase.testStepConfigRequest)

if testCase.expected != got {
t.Errorf("expected %s, got %s", testCase.expected, got)
}
})
}
}
6 changes: 6 additions & 0 deletions config/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

// Package config implements functionality for supporting native
// Terraform configuration and variables for testing purposes.
package config
63 changes: 63 additions & 0 deletions config/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package config

import (
"path/filepath"
"strconv"
)

// StaticFile returns the supplied file.
func StaticFile(file string) func(TestStepConfigRequest) string {
return func(_ TestStepConfigRequest) string {
return file
}
}

// TestNameFile returns the name of the test suffixed with the supplied
// file and prefixed with "testdata".
//
// For example, given test code:
//
// func TestExampleCloudThing_basic(t *testing.T) {
// resource.Test(t, resource.TestCase{
// Steps: []resource.TestStep{
// {
// ConfigFile: config.TestNameFile("test.tf"),
// },
// },
// })
// }
//
// The testing configuration will be expected in the
// testdata/TestExampleCloudThing_basic/test.tf file.
func TestNameFile(file string) func(TestStepConfigRequest) string {
return func(req TestStepConfigRequest) string {
return filepath.Join("testdata", req.TestName, file)
}
}

// TestStepFile returns the name of the test suffixed with the test
// step number and the supplied file, and prefixed with "testdata".
//
// For example, given test code:
//
// func TestExampleCloudThing_basic(t *testing.T) {
// resource.Test(t, resource.TestCase{
// Steps: []resource.TestStep{
// {
// ConfigFile: config.TestStepFile("test.tf"),
// },
// },
// })
// }
//
// The testing configuration will be expected in the
// testdata/TestExampleCloudThing_basic/1/test.tf file
// as TestStepConfigRequest.StepNumber is one-based.
func TestStepFile(file string) func(TestStepConfigRequest) string {
return func(req TestStepConfigRequest) string {
return filepath.Join("testdata", req.TestName, strconv.Itoa(req.StepNumber), file)
}
}
54 changes: 54 additions & 0 deletions config/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package config_test

import (
"testing"

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

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

testCases := map[string]struct {
testStepConfigFunc config.TestStepConfigFunc
testStepConfigRequest config.TestStepConfigRequest
expected string
}{
"static_file": {
testStepConfigFunc: config.StaticFile("name_of_file"),
expected: "name_of_file",
},
"test_name_file": {
testStepConfigFunc: config.TestNameFile("test.tf"),
testStepConfigRequest: config.TestStepConfigRequest{
TestName: "TestTestStepConfigFunc_Exec",
},
expected: "testdata/TestTestStepConfigFunc_Exec/test.tf",
},
"test_step_file": {
testStepConfigFunc: config.TestStepFile("test.tf"),
testStepConfigRequest: config.TestStepConfigRequest{
StepNumber: 1,
TestName: "TestTestStepConfigFunc_Exec",
},
expected: "testdata/TestTestStepConfigFunc_Exec/1/test.tf",
},
}

for name, testCase := range testCases {
name, testCase := name, testCase

t.Run(name, func(t *testing.T) {
t.Parallel()

got := testCase.testStepConfigFunc.Exec(testCase.testStepConfigRequest)

if testCase.expected != got {
t.Errorf("expected %s, got %s", testCase.expected, got)
}
})
}
}
Loading

0 comments on commit e46c64f

Please sign in to comment.