autogold

package module
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Dec 20, 2022 License: Apache-2.0, MIT, Apache-2.0, + 1 more Imports: 24 Imported by: 2

README

autogold - automatically update your Go tests Hexops logo

Go Reference

Go CI codecov Go Report Card

autogold makes go test -update automatically update your Go tests (golden files and Go values in e.g. foo_test.go).

~5m introduction available on YouTube:

"It's 2021: you shouldn't have to update Go tests manually"

Automatic golden files

Write in a Go test:

import "github.com/hexops/autogold"
...
autogold.Equal(t, got)

go test -update will now create/update a testdata/<test name>.golden file for you automatically.

Automatic inline test updating

Write in a Go test:

want := autogold.Want("my_test", nil)
want.Equal(t, got)

go test -update will automatically update the autogold.Want("my_test", ...) call with the Go syntax for whatever value your test got (complex Go struct, slices, strings, etc.)

Diffs

Anytime your test produces a result that is unexpected, you'll get very nice diffs showing exactly what changed. It does this by converting values at runtime directly to a formatted Go AST, and using the same diffing library the Go language server uses:

--- FAIL: TestEqual (0.08s)
    autogold.go:91: mismatch (-want +got):
        --- want
        +++ got
        @@ -1 +1 @@
        +&example.Baz{Name: "Jane", Age: 31}

Subtesting

Use table-driven Go subtests? autogold.Want and go test -update will automatically find and replace the nil values for you:

func TestTime(t *testing.T) {
	testCases := []struct {
		gmt  string
		loc  string
		want autogold.Value
	}{
		{"12:31", "Europe/Zuri", autogold.Want("Europe", nil)},
		{"12:31", "America/New_York", autogold.Want("America", nil)},
		{"08:08", "Australia/Sydney", autogold.Want("Australia", nil)},
	}
	for _, tc := range testCases {
		t.Run(tc.want.Name(), func(t *testing.T) {
			loc, err := time.LoadLocation(tc.loc)
			if err != nil {
				t.Fatal("could not load location")
			}
			gmt, _ := time.Parse("15:04", tc.gmt)
			got := gmt.In(loc).Format("15:04")
			tc.want.Equal(t, got)
		})
	}
}

It works by finding the relevant autogold.Want("<unique name>", ...) call below the named TestTime function, and then replacing the nil parameter (or anything that was there.)

What are golden files, when should they be used?

Golden files are used by the Go authors for testing the standard library, the gofmt tool, etc. and are a common pattern in the Go community for snapshot testing. See also "Testing with golden files in Go" - Chris Reeves

Golden files make the most sense when you'd otherwise have to write a complex multi-line string or large Go structure inline in your test, making it hard to read.

In most cases, you should prefer inline snapshots, subtest golden values, or traditional Go tests.

Command line syntax: put -update at the end

-update should go at the end of your go test command, otherwise for some reason stdout will be considered a terminal and color will be turned on for libraries like fatih/color. Example:

go test -count=1 -run TestSomething . -update

Custom formatting

valast is used to produce Go syntax at runtime for the Go value you provide. If the default output is not to your liking, you have options:

  • Pass a string to autogold: It will be formatted as a Go string for you in the resulting .golden file / in Go tests.
  • Use your own formatting (JSON, etc.): Make your got value of type autogold.Raw("foobar"), and it will be used as-is for .golden files (not allowed with inline tests.)
  • Exclude unexported fields: autogold.Equal(t, got, autogold.ExportedOnly())

Backwards compatibility

  • As is the case with gofmt, different Go versions may produce different formattings (although rare.)
  • Minor versions of autogold (e.g. v1.0, v1.1) may alter the formatting of .golden files, although we will be mindful of such changes.
  • Major versions of autogold (e.g. v1, v2) will be used for any major changes in output that would be difficult to review (we expect this will be rare in practice.)

Alternatives comparison

The following are alternatives to autogold, making note of the differences we found that let us to create autogold:

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Equal

func Equal(t *testing.T, got interface{}, opts ...Option)

Equal checks if got is equal to the saved `testdata/<test name>.golden` test file. If it is not, t.Fatal is called with a multi-line diff comparison.

If the `go test -update` flag is specified, the .golden files will be updated/created automatically.

If the input value is of type Raw, its contents will be directly used instead of the value being formatted as a Go literal.

Types

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option configures specific behavior for Equal.

func Dir

func Dir(dir string) Option

Dir specifies a customer directory to use for writing the golden files, instead of the default "testdata/".

func ExportedOnly added in v0.9.5

func ExportedOnly() Option

ExportedOnly is an option that includes exported fields in the output only.

func Name

func Name(name string) Option

Name specifies a name to use for the testdata/<name>.golden file instead of the default test name.

type Raw added in v0.9.5

type Raw string

Raw denotes a raw string.

type Value added in v0.9.5

type Value interface {
	// Name returns the value name.
	Name() string

	// Equal checks if `got` matches the desired test value, invoking t.Fatal otherwise.
	Equal(t *testing.T, got interface{}, opts ...Option)
}

Value describes a desired value for a Go test, see Want for more information.

func Want added in v0.9.5

func Want(name string, want interface{}) Value

Want returns a desired Value which can later be checked for equality against a gotten value.

The name parameter must be a Go string literal (NOT a variable or expression), and must be unique within the Go test function.

When `-update` is specified, autogold will find and replace in the test file by looking for an instance of e.g. `autogold.Want("bar", ...)` beneath the calling `TestFoo` function and replacing the `want` value parameter.

Directories

Path Synopsis
internal
test
Package test provides a package for testing autogold; primarily one that lives outside of the module root directory.
Package test provides a package for testing autogold; primarily one that lives outside of the module root directory.

Jump to

Keyboard shortcuts

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