gilt

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 29, 2024 License: MIT Imports: 9 Imported by: 0

README

Gilt

A library for performing Golden Tests in Go.

  • Read and update golden files
  • Use any assertion function

Basic Usage

[!TIP] See the golden_examples_test.go for more examples.

Reading and writing Golden files as strings

Test code:

func hello(to string) string {
	return "Hello, " + to + "!"
}

func TestNewStringGolden(t *testing.T) {
	golden := gilt.NewStringGolden(t.Name())

	tests := []struct {
		name string
	}{
		{"world"},
		{"gopher"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			actual := hello(tt.name)
			golden.Assert(t, actual, tt.name, func(t *testing.T, actual string, expected string) {
				if actual != expected {
					t.Errorf("expected: %s\n, but was: %s", expected, actual)
				}
			})
		})
	}
}

Updating the golden file:

You can update the golden file by running the test with the -update flag.

$ go test -update

The following golden file will be generated:

testdata
└── testdata/TestNewStringGolden
    └── testdata/TestNewStringGolden/golden
        ├── testdata/TestNewStringGolden/golden/gopher.golden
        └── testdata/TestNewStringGolden/golden/world.golden

gopher.golden:

Hello, gopher!

Then you can run the test.

$ go test
Reading and updating Golden files using json.Marshal/Unmarshal

Test code:

type HelloMessage struct {
	Message string `json:"message"`
}

func helloMessage(to string) HelloMessage {
	return HelloMessage{"Hello, " + to + "!"}
}

func TestNewJSONGolden(t *testing.T) {
	golden := gilt.NewJSONGolden[HelloMessage, HelloMessage](t.Name())

	tests := []struct {
		name string
	}{
		{"world"},
		{"gopher"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			actual := helloMessage(tt.name)
			golden.Assert(t, actual, tt.name, func(t *testing.T, actual HelloMessage, expected HelloMessage) {
				if actual.Message != expected.Message {
					t.Errorf("expected: %v\n, but was: %v", expected, actual)
				}
			})
		})
	}
}

By running go test -update, the following golden file will be generated:

testdata
└── testdata/TestNewJSONGolden
    └── testdata/TestNewJSONGolden/golden
        ├── testdata/TestNewJSONGolden/golden/gopher.golden
        └── testdata/TestNewJSONGolden/golden/world.golden

gopher.golden:

{
  "message": "Hello, gopher!"
}

When running go test, the golden file will be unmarshaled into the HelloMessage type and passed to the assertion function.
You can use any assertion function you like.

	golden.Assert(t, actual, tt.name, func(t *testing.T, actual HelloMessage, expected HelloMessage) {
		if actual.Message != expected.Message {
			t.Errorf("expected: %v\n, but was: %v", expected, actual)
		}
	})

Advanced Usage

Customizing the reading and updating of Golden files

You can customize the reading and updating of Golden files by implementing the each of the following interfaces:

%%{init:{'theme':'neutral'}}%%
graph TB
  subgraph "Golden[TActual,TExpected]"
    Assert(("Assert"))
    GoldenFiles[("golden files")]
    IsUpdater["IsUpdater"]

    Assert ==> IsUpdater
    
    IsUpdater ==> Update
    IsUpdater ==> Load
    
    Assert --"actual TActual"--> Saver
    subgraph "Update"
      Saver["Saver"]
      Writer["Writer"]
      Saver ==> Writer
    end
    Writer --> GoldenFiles

    subgraph "Load"
      Reader["Reader"]
      Loader["Loader"]
      Reader -.-> Loader
      
    end
    GoldenFiles -.-> Reader
  
  end
  
  assertion[["assertion"]]
  Loader -."expected TExpected".-> assertion
  Assert --"actual TActual"--> assertion

For example, you can specify a gilt.SaveLines function for Saver and a gilt.LoadLines function for Loader as follows:

golden := gilt.New(
	t.Name(),
	gilt.WithSaver[[]string, iter.Seq[string]](
		gilt.SaverFunc[[]string](gilt.SaveLines[string]),
	),
	gilt.WithLoader[[]string](
		gilt.LoaderFunc[iter.Seq[string]](gilt.LoadLines),
	),
)

Of course, you can also specify a function that you have implemented yourself.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultPathHandler

func DefaultPathHandler(t *testing.T, namespace string, name string) string

func LoadAndUnmarshalJSON

func LoadAndUnmarshalJSON[TExpected any](t *testing.T, name string, reader Reader) TExpected

func LoadBytes

func LoadBytes(t *testing.T, name string, reader Reader) []byte

func LoadLines

func LoadLines(t *testing.T, name string, reader Reader) iter.Seq[string]

func LoadString

func LoadString(t *testing.T, name string, reader Reader) string

func SaveAsJSON

func SaveAsJSON[TActual any](t *testing.T, actual TActual, name string, writer Writer)

func SaveAsString

func SaveAsString[TActual any](t *testing.T, actual TActual, name string, writer Writer)

func SaveBytes

func SaveBytes(t *testing.T, actual []byte, name string, writer Writer)

func SaveLines

func SaveLines[TActualElm ~string](t *testing.T, actual []TActualElm, name string, writer Writer)

func SetIsUpdateFunc

func SetIsUpdateFunc(f func(t *testing.T, name string) bool)

Types

type Golden

type Golden[TActual, TExpected any] struct {
	// contains filtered or unexported fields
}

func New

func New[TActual any, TExpected any](
	namespace string,
	opts ...Option[TActual, TExpected],
) *Golden[TActual, TExpected]

func NewBytesGolden

func NewBytesGolden(namespace string, opts ...Option[[]byte, []byte]) *Golden[[]byte, []byte]

func NewJSONGolden

func NewJSONGolden[TActual, TExpected any](namespace string, opts ...Option[TActual, TExpected]) *Golden[TActual, TExpected]

func NewStringGolden

func NewStringGolden(namespace string, opts ...Option[string, string]) *Golden[string, string]

func (*Golden[TActual, TExpected]) Assert

func (g *Golden[TActual, TExpected]) Assert(
	t *testing.T, actual TActual, name string,
	assertion func(t *testing.T, actual TActual, expected TExpected),
)

type GoldenFile

type GoldenFile struct {
	// contains filtered or unexported fields
}

func NewGoldenFile

func NewGoldenFile(namespace string, opts ...GoldenFileOption) *GoldenFile

func (*GoldenFile) Open

func (g *GoldenFile) Open(t *testing.T, name string) *os.File

func (*GoldenFile) Read

func (g *GoldenFile) Read(t *testing.T, name string) []byte

func (*GoldenFile) Write

func (g *GoldenFile) Write(t *testing.T, name string, data []byte)

type GoldenFileOption

type GoldenFileOption func(*GoldenFile)

func GoldenFileWithPathHandler

func GoldenFileWithPathHandler(f func(t *testing.T, namespace string, name string) string) GoldenFileOption

type IsUpdater

type IsUpdater interface {
	IsUpdate(t *testing.T, name string) bool
}

type IsUpdaterFunc

type IsUpdaterFunc func(t *testing.T, name string) bool

func (IsUpdaterFunc) IsUpdate

func (f IsUpdaterFunc) IsUpdate(t *testing.T, name string) bool

type Loader

type Loader[TExpected any] interface {
	Load(t *testing.T, name string, reader Reader) TExpected
}

type LoaderFunc

type LoaderFunc[TExpected any] func(t *testing.T, name string, reader Reader) TExpected

func (LoaderFunc[TExpected]) Load

func (f LoaderFunc[TExpected]) Load(t *testing.T, name string, reader Reader) TExpected

type Opener

type Opener interface {
	Open(t *testing.T, name string) *os.File
}

type Option

type Option[TActual, TExpected any] func(*Golden[TActual, TExpected])

func WithGoldenFile

func WithGoldenFile[TActual, TExpected any](goldenFile ReadWriter) Option[TActual, TExpected]

func WithIsUpdater

func WithIsUpdater[TActual, TExpected any](updater IsUpdater) Option[TActual, TExpected]

func WithLoader

func WithLoader[TActual, TExpected any](loader Loader[TExpected]) Option[TActual, TExpected]

func WithSaver

func WithSaver[TActual, TExpected any](saver Saver[TActual]) Option[TActual, TExpected]

type ReadWriter

type ReadWriter interface {
	Reader
	Writer
}

type Reader

type Reader interface {
	Read(t *testing.T, name string) []byte
}

type Saver

type Saver[TActual any] interface {
	Save(t *testing.T, actual TActual, name string, writer Writer)
}

type SaverFunc

type SaverFunc[TActual any] func(t *testing.T, actual TActual, name string, writer Writer)

func (SaverFunc[TActual]) Save

func (f SaverFunc[TActual]) Save(t *testing.T, actual TActual, name string, writer Writer)

type Writer

type Writer interface {
	Write(t *testing.T, name string, data []byte)
}

Jump to

Keyboard shortcuts

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