helper/resource: Add ParallelTest() function to allow opt-in acceptance testing concurrency with t.Parallel()

While this initial implementation is a very simple wrapper function, implementing this in the helper/resource package provides some downstream benefits:
* Provides a standard interface for plugin developers to enable parallel acceptance testing
* Existing plugins can simply convert resource.Test to resource.ParallelTest references (as appropriate) to enable the functionality, rather than worrying about additional line(s) to each acceptance test function or TestCase
* Potential enhancements to ParallelTest (e.g. adding an environment variable to skip enabling the behavior) are consistently propagated
This commit is contained in:
Brian Flad 2018-08-15 14:03:13 -04:00
parent 4c08bf8b43
commit 798162125b
2 changed files with 35 additions and 6 deletions

View File

@ -418,6 +418,17 @@ func LogOutput(t TestT) (logOutput io.Writer, err error) {
return return
} }
// ParallelTest performs an acceptance test on a resource, allowing concurrency
// with other ParallelTest.
//
// Tests will fail if they do not properly handle conditions to allow multiple
// tests to occur against the same resource or service (e.g. random naming).
// All other requirements of the Test function also apply to this function.
func ParallelTest(t TestT, c TestCase) {
t.Parallel()
Test(t, c)
}
// Test performs an acceptance test on a resource. // Test performs an acceptance test on a resource.
// //
// Tests are not run unless an environmental variable "TF_ACC" is // Tests are not run unless an environmental variable "TF_ACC" is
@ -1128,6 +1139,7 @@ type TestT interface {
Fatal(args ...interface{}) Fatal(args ...interface{})
Skip(args ...interface{}) Skip(args ...interface{})
Name() string Name() string
Parallel()
} }
// This is set to true by unit tests to alter some behavior // This is set to true by unit tests to alter some behavior

View File

@ -45,6 +45,15 @@ func (p *resetProvider) TestReset() error {
return p.TestResetError return p.TestResetError
} }
func TestParallelTest(t *testing.T) {
mt := new(mockT)
ParallelTest(mt, TestCase{})
if !mt.ParallelCalled {
t.Fatal("Parallel() not called")
}
}
func TestTest(t *testing.T) { func TestTest(t *testing.T) {
mp := &resetProvider{ mp := &resetProvider{
MockResourceProvider: testProvider(), MockResourceProvider: testProvider(),
@ -112,6 +121,9 @@ func TestTest(t *testing.T) {
if mt.failed() { if mt.failed() {
t.Fatalf("test failed: %s", mt.failMessage()) t.Fatalf("test failed: %s", mt.failMessage())
} }
if mt.ParallelCalled {
t.Fatal("Parallel() called")
}
if !checkStep { if !checkStep {
t.Fatal("didn't call check for step") t.Fatal("didn't call check for step")
} }
@ -696,6 +708,7 @@ type mockT struct {
ErrorArgs []interface{} ErrorArgs []interface{}
FatalCalled bool FatalCalled bool
FatalArgs []interface{} FatalArgs []interface{}
ParallelCalled bool
SkipCalled bool SkipCalled bool
SkipArgs []interface{} SkipArgs []interface{}
@ -714,6 +727,10 @@ func (t *mockT) Fatal(args ...interface{}) {
t.f = true t.f = true
} }
func (t *mockT) Parallel() {
t.ParallelCalled = true
}
func (t *mockT) Skip(args ...interface{}) { func (t *mockT) Skip(args ...interface{}) {
t.SkipCalled = true t.SkipCalled = true
t.SkipArgs = args t.SkipArgs = args