provider/test: a test provider

Here we also introduce a `test` provider meant as an aid to exposing
via automated tests issues involving interactions between
`helper/schema` and Terraform core.

This has been helpful so far in diagnosing `ignore_changes` problems,
and I imagine it will be helpful in other contexts as well.

We'll have to be careful to prevent the `test` provider from becoming a
dumping ground for poorly specified tests that have a clear home
elsewhere. But for bug exposure I think it's useful to have.
This commit is contained in:
Paul Hinze 2016-03-15 10:11:28 -05:00
parent 3bb990311d
commit c3e27b3e0a
5 changed files with 143 additions and 1 deletions

View File

@ -0,0 +1,19 @@
package test
import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
func Provider() terraform.ResourceProvider {
return &schema.Provider{
ResourcesMap: map[string]*schema.Resource{
"test_resource": testResource(),
},
ConfigureFunc: providerConfigure,
}
}
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
return nil, nil
}

View File

@ -0,0 +1,16 @@
package test
import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider
func init() {
testAccProvider = Provider().(*schema.Provider)
testAccProviders = map[string]terraform.ResourceProvider{
"test": testAccProvider,
}
}

View File

@ -0,0 +1,53 @@
package test
import (
"fmt"
"github.com/hashicorp/terraform/helper/schema"
)
func testResource() *schema.Resource {
return &schema.Resource{
Create: testResourceCreate,
Read: testResourceRead,
Update: testResourceUpdate,
Delete: testResourceDelete,
Schema: map[string]*schema.Schema{
"required": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"optional": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"optional_force_new": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
},
}
}
func testResourceCreate(d *schema.ResourceData, meta interface{}) error {
d.SetId("testId")
// Required must make it through to Create
if _, ok := d.GetOk("required"); !ok {
return fmt.Errorf("Missing attribute 'required', but it's required!")
}
return nil
}
func testResourceRead(d *schema.ResourceData, meta interface{}) error {
return nil
}
func testResourceUpdate(d *schema.ResourceData, meta interface{}) error {
return nil
}
func testResourceDelete(d *schema.ResourceData, meta interface{}) error {
return nil
}

View File

@ -0,0 +1,32 @@
package test
import (
"strings"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestResource_basic(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
Providers: testAccProviders,
CheckDestroy: testAccCheckResourceDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: strings.TrimSpace(`
resource "test_resource" "foo" {
required = "yep"
}
`),
Check: func(s *terraform.State) error {
return nil
},
},
},
})
}
func testAccCheckResourceDestroy(s *terraform.State) error {
return nil
}

View File

@ -19,6 +19,10 @@ import (
const TestEnvVar = "TF_ACC"
// UnitTestOverride is a value that when set in TestEnvVar indicates that this
// is a unit test borrowing the acceptance testing framework.
const UnitTestOverride = "UnitTestOverride"
// TestCheckFunc is the callback type used with acceptance tests to check
// the state of a resource. The state passed in is the latest state known,
// or in the case of being after a destroy, it is the last known state when
@ -108,6 +112,8 @@ func Test(t TestT, c TestCase) {
return
}
isUnitTest := (os.Getenv(TestEnvVar) == UnitTestOverride)
logWriter, err := logging.LogOutput()
if err != nil {
t.Error(fmt.Errorf("error setting up logging: %s", err))
@ -115,7 +121,7 @@ func Test(t TestT, c TestCase) {
log.SetOutput(logWriter)
// We require verbose mode so that the user knows what is going on.
if !testTesting && !testing.Verbose() {
if !testTesting && !testing.Verbose() && !isUnitTest {
t.Fatal("Acceptance tests must be run with the -v flag on tests")
return
}
@ -173,6 +179,22 @@ func Test(t TestT, c TestCase) {
}
}
// UnitTest is a helper to force the acceptance testing harness to run in the
// normal unit test suite. This should only be used for resource that don't
// have any external dependencies.
func UnitTest(t TestT, c TestCase) {
oldEnv := os.Getenv(TestEnvVar)
if err := os.Setenv(TestEnvVar, UnitTestOverride); err != nil {
t.Fatal(err)
}
defer func() {
if err := os.Setenv(TestEnvVar, oldEnv); err != nil {
t.Fatal(err)
}
}()
Test(t, c)
}
func testStep(
opts terraform.ContextOpts,
state *terraform.State,