Help us shape the future of Go! Take the 2026 Go Developer Survey

acctest

package
v0.6.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2026 License: MPL-2.0 Imports: 7 Imported by: 3

Documentation

Overview

Package acctest provides an acceptance testing framework for testing builders and provisioners.

Writing Provisioner Acceptance Tests

Packer has implemented a `ProvisionerTestCase` structure to help write provisioner acceptance tests.

```go

type ProvisionerTestCase struct {
  // Check is called after this step is executed in order to test that
  // the step executed successfully. If this is not set, then the next
  // step will be called
  Check func(*exec.Cmd, string) error
  // IsCompatible checks whether a provisioner is able to run against a
  // given builder type and guest operating system, and returns a boolean.
  // if it returns true, the test combination is okay to run. If false, the
  // test combination is not okay to run.
  IsCompatible func(builderType string, BuilderGuestOS string) bool
  // Name is the name of the test case. Be simple but unique and descriptive.
  Name string
  // Setup, if non-nil, will be called once before the test case
  // runs. This can be used for some setup like setting environment
  // variables, or for validation prior to the
  // test running. For example, you can use this to make sure certain
  // binaries are installed, or text fixtures are in place.
  Setup func() error
  // Teardown will be called before the test case is over regardless
  // of if the test succeeded or failed. This should return an error
  // in the case that the test can't guarantee all resources were
  // properly cleaned up.
  Teardown builderT.TestTeardownFunc
  // Template is the provisioner template to use.
  // The provisioner template fragment must be a json-formatted string
  // containing the provisioner definition but no other portions of a packer
  // template. For
  // example:
  //
  // ```json
  // {
  //  "type": "shell-local",
  //  "inline", ["echo hello world"]
  // }
  //```
  //
  // is a valid entry for "template" here, but the complete Packer template:
  //
  // ```json
  // {
  //  "provisioners": [
  //    {
  //      "type": "shell-local",
  //      "inline", ["echo hello world"]
  //    }
  //  ]
  // }
  // ```
  //
  // is invalid as input.
  //
  // You may provide multiple provisioners in the same template. For example:
  // ```json
  // {
  //  "type": "shell-local",
  //  "inline", ["echo hello world"]
  // },
  // {
  //  "type": "shell-local",
  //  "inline", ["echo hello world 2"]
  // }
  // ```
  Template string
  // Type is the type of provisioner.
  Type string
}

```

To start writing a new provisioner acceptance test, you should add a test file named `provisioner_acc_test.go` in the same folder as your provisioner is defined. Create a test case by implementing the above struct, and run it by calling `provisioneracc.TestProvisionersAgainstBuilders(testCase, t)`

The following example has been adapted from a shell-local provisioner test:

``` import (

"github.com/hashicorp/packer-plugin-sdk/acctest/provisioneracc"
"github.com/hashicorp/packer-plugin-sdk/acctest/testutils"

)

// ...

func TestAccShellProvisioner_basic(t *testing.T) {
  // Create a json template fragment containing just the provisioners you want
  // to run.
  templateString := `{
    "type": "shell-local",
    "script": "test-fixtures/script.sh",
    "max_retries" : 5
}`

  // instantiate a test case.
  testCase := &provisioneracc.ProvisionerTestCase{
    IsCompatible: func() bool {return true},
    Name:         "shell-local-provisioner-basic",
    Teardown: func() error {
      testutils.CleanupFiles("test-fixtures/file.txt")
      return nil
    },
    Template: templateString,
    Type:     "shell-local",
    Check: func(buildcommand *exec.Cmd, logfile string) error {
      if buildcommand.ProcessState != nil {
        if buildcommand.ProcessState.ExitCode() != 0 {
          return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
        }
      }
      filecontents, err := loadFile("file.txt")
      if err != nil {
        return err
      }
      if !strings.Contains(filecontents, "hello") {
        return fmt.Errorf("file contents were wrong: %s", filecontents)
      }
      return nil
    },
  }

  provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
}

```

After writing the struct and implementing the interface, now is time to write the test that will run all of this code you wrote. Your test should be like:

```go

func TestShellProvisioner(t *testing.T) {
	acc.TestProvisionersPreCheck("shell", t)
	acc.TestProvisionersAgainstBuilders(new(ShellProvisionerAccTest), t)
}

```

The method `TestProvisionersAgainstBuilders` will run the provisioner against all available and compatible builders. If there are not builders compatible with the test you want to run, you can add a builder using the following steps:

Create a subdirectory in provisioneracc/test-fixtures for the type of builder you are adding. In this subdirectory, add one json file containing a single builder fragment. For example, one of our amazon-ebs builders is defined in provisioneracc/test-fixtures/amazon-ebs/amazon-ebs.txt and contains:

```json

{
  "type": "amazon-ebs",
  "ami_name": "packer-acc-test",
  "instance_type": "t2.micro",
  "region": "us-east-1",
  "ssh_username": "ubuntu",
  "source_ami_filter": {
    "filters": {
      "virtualization-type": "hvm",
      "name": "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*",
      "root-device-type": "ebs"
    },
    "owners": ["099720109477"],
    "most_recent": true
  },
  "force_deregister" : true,
  "tags": {
    "packer-test": "true"
  }
}

```

note that this fragment does not contain anything other than a single builder definition. The testing framework will combine this with the provisioner fragment to create a working json template.

In order to tell the testing framework how to use this builder fragment, you need to implement a `BuilderFixture` struct:

```go

type BuilderFixture struct {
  // Name is the name of the builder fixture.
  // Be simple and descriptive.
  Name string
  // Setup creates necessary extra test fixtures, and renders their values
  // into the BuilderFixture.Template.
  Setup func()
  // Template is the path to a builder template fragment.
  // The builder template fragment must be a json-formatted file containing
  // the builder definition but no other portions of a packer template. For
  // example:
  //
  // ```json
  // {
  //  "type": "null",
  //  "communicator", "none"
  // }
  //```
  //
  // is a valid entry for "template" here, but the complete Packer template:
  //
  // ```json
  // {
  //  "builders": [
  //    "type": "null",
  //    "communicator": "none"
  //  ]
  // }
  // ```
  //
  // is invalid as input.
  //
  // Only provide one builder template fragment per file.
  TemplatePath string

  // GuestOS says what guest os type the builder template fragment creates.
  // Valid values are "windows", "linux" or "darwin" guests.
  GuestOS string

  // HostOS says what host os type the builder is capable of running on.
  // Valid values are "any", windows", or "posix". If you set "posix", then
  // this builder can run on a "linux" or "darwin" platform. If you set
  // "any", then this builder can be used on any platform.
  HostOS string

  Teardown builderT.TestTeardownFunc
}

``` Implement this struct to the file "provisioneracc/builders.go", then add the new implementation to the `BuildersAccTest` map in `provisioneracc/provisioners.go`

Once you finish these steps, you should be ready to run your new provisioner acceptance test by setting the name used in the BuildersAccTest map as your `ACC_TEST_BUILDERS` environment variable.

Index

Constants

View Source
const TestEnvVar = "PACKER_ACC"

TestEnvVar must be set to a non-empty value for acceptance tests to run.

Variables

This section is empty.

Functions

func TestPlugin added in v0.0.10

func TestPlugin(t *testing.T, testCase *PluginTestCase)

Types

type PluginTestCase added in v0.0.10

type PluginTestCase struct {
	// Init, if true `packer init` will be executed prior to `packer build`.
	Init bool
	// BuildExtraArgs is the list of arguments to be passed as extra to the packer build
	// command.
	// These arguments are injected before the already present `--machine-readable` option.
	BuildExtraArgs []string
	// CheckInit is called after packer init step is executed in order to test that
	// the step executed successfully. If this is not set, then the next
	// step will be called
	CheckInit func(*exec.Cmd, string) error

	// Check is called after this step is executed in order to test that
	// the step executed successfully. If this is not set, then the next
	// step will be called
	Check func(*exec.Cmd, string) error
	// Name is the name of the test case. Be simple but unique and descriptive.
	Name string
	// Setup, if non-nil, will be called once before the test case
	// runs. This can be used for some setup like setting environment
	// variables, or for validation prior to the
	// test running. For example, you can use this to make sure certain
	// binaries are installed, or text fixtures are in place.
	Setup func() error
	// Teardown will be called before the test case is over regardless
	// of if the test succeeded or failed. This should return an error
	// in the case that the test can't guarantee all resources were
	// properly cleaned up.
	Teardown TestTeardownFunc
	// Template is the testing HCL2 template to use.
	Template string
	// Type is the type of the plugin.
	Type string
}

PluginTestCase is a single set of tests to run for a plugin. A PluginTestCase should generally map 1:1 to each test method for your acceptance tests. Requirements: - If not using 'packer init', the plugin must be previously installed - Packer must be installed locally

type TestTeardownFunc

type TestTeardownFunc func() error

TestTeardownFunc is the callback used for Teardown in TestCase.

Directories

Path Synopsis
Package provisioneracc creates a framework for provisioner acceptance testing.
Package provisioneracc creates a framework for provisioner acceptance testing.
Package testutils provides some simple ease-of-use tools for implementing acceptance testing.
Package testutils provides some simple ease-of-use tools for implementing acceptance testing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL