mirror of
https://github.com/jimeh/go-golden.git
synced 2026-02-19 11:16:47 +00:00
wip: unfinished further tweaks
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
bin/*
|
||||
coverage.out
|
||||
|
||||
testdata/*
|
||||
!testdata/TestExample*
|
||||
testdata/TestFile*
|
||||
testdata/TestGet*
|
||||
testdata/TestSet*
|
||||
|
||||
1
Makefile
1
Makefile
@@ -51,6 +51,7 @@ $(eval $(call tool,gofumpt,mvdan.cc/gofumpt))
|
||||
$(eval $(call tool,goimports,golang.org/x/tools/cmd/goimports))
|
||||
$(eval $(call tool,golangci-lint,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.44))
|
||||
$(eval $(call tool,gomod,github.com/Helcaraxan/gomod))
|
||||
$(eval $(call tool,mockgen,mockgen,github.com/golang/mock/mockgen@v1.6.0))
|
||||
|
||||
.PHONY: tools
|
||||
tools: $(TOOLS)
|
||||
|
||||
1
go.mod
1
go.mod
@@ -3,6 +3,7 @@ module github.com/jimeh/go-golden
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/jimeh/envctl v0.1.0
|
||||
github.com/jimeh/go-mocktesting v0.1.0
|
||||
github.com/spf13/afero v1.6.0
|
||||
|
||||
18
go.sum
18
go.sum
@@ -1,5 +1,7 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/jimeh/envctl v0.1.0 h1:KTv3D+pi5M4/PgFVE/W8ssWqiZP3pDJ8Cga50L+1avo=
|
||||
github.com/jimeh/envctl v0.1.0/go.mod h1:aM27ffBbO1yUBKUzgJGCUorS4z+wyh+qhQe1ruxXZZo=
|
||||
github.com/jimeh/go-mocktesting v0.1.0 h1:y0tLABo3V4i9io7m6TiXdXbU3IVMjtPvWkr+A0+aLTM=
|
||||
@@ -16,15 +18,31 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
278
golden.go
278
golden.go
@@ -2,124 +2,120 @@
|
||||
// with a focus on simplicity through it's default behavior.
|
||||
//
|
||||
// Golden file names are based on the name of the test function and any subtest
|
||||
// names by calling t.Name(). File names are sanitized to ensure they're
|
||||
// names by calling t.Name(). File names are sanitized to ensure they are
|
||||
// compatible with Linux, macOS and Windows systems regardless of what
|
||||
// characters might be in a subtest's name.
|
||||
//
|
||||
// Usage
|
||||
// # Usage
|
||||
//
|
||||
// Typical usage should look something like this:
|
||||
//
|
||||
// func TestExampleMyStruct(t *testing.T) {
|
||||
// got, err := json.Marshal(&MyStruct{Foo: "Bar"})
|
||||
// require.NoError(t, err)
|
||||
// func TestExampleMyStruct(t *testing.T) {
|
||||
// got, err := json.Marshal(&MyStruct{Foo: "Bar"})
|
||||
// require.NoError(t, err)
|
||||
//
|
||||
// if golden.Update() {
|
||||
// golden.Set(t, got)
|
||||
// }
|
||||
// want := golden.Get(t)
|
||||
// want := golden.Do(t, got)
|
||||
//
|
||||
// assert.Equal(t, want, got)
|
||||
// }
|
||||
// assert.Equal(t, want, got)
|
||||
// }
|
||||
//
|
||||
// The above example will read/write to:
|
||||
// The above example will attempt to read/write to:
|
||||
//
|
||||
// testdata/TestExampleMyStruct.golden
|
||||
// testdata/TestExampleMyStruct.golden
|
||||
//
|
||||
// The call to golden.Do() is equivalent to:
|
||||
//
|
||||
// if golden.Update() {
|
||||
// golden.Set(t, got)
|
||||
// }
|
||||
// want := golden.Get(t)
|
||||
//
|
||||
// To update the golden file (have golden.Update() return true), simply set the
|
||||
// GOLDEN_UPDATE environment variable to one of "1", "y", "t", "yes", "on", or
|
||||
// "true" when running tests.
|
||||
//
|
||||
// Sub-Tests
|
||||
// # Sub-Tests
|
||||
//
|
||||
// As the golden filename is based on t.Name(), it works with sub-tests too,
|
||||
// ensuring each sub-test gets it's own golden file. For example:
|
||||
//
|
||||
// func TestExampleMyStructTabular(t *testing.T) {
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// obj *MyStruct
|
||||
// }{
|
||||
// {name: "empty struct", obj: &MyStruct{}},
|
||||
// {name: "full struct", obj: &MyStruct{Foo: "Bar"}},
|
||||
// }
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// got, err := json.Marshal(tt.obj)
|
||||
// require.NoError(t, err)
|
||||
// func TestExampleMyStructTabular(t *testing.T) {
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// obj *MyStruct
|
||||
// }{
|
||||
// {name: "empty struct", obj: &MyStruct{}},
|
||||
// {name: "full struct", obj: &MyStruct{Foo: "Bar"}},
|
||||
// }
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// got, err := json.Marshal(tt.obj)
|
||||
// require.NoError(t, err)
|
||||
//
|
||||
// if golden.Update() {
|
||||
// golden.Set(t, got)
|
||||
// }
|
||||
// want := golden.Get(t)
|
||||
// want := golden.Do(t, got)
|
||||
//
|
||||
// assert.Equal(t, want, got)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// assert.Equal(t, want, got)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// The above example will read/write to:
|
||||
//
|
||||
// testdata/TestExampleMyStructTabular/empty_struct.golden
|
||||
// testdata/TestExampleMyStructTabular/full_struct.golden
|
||||
// testdata/TestExampleMyStructTabular/empty_struct.golden
|
||||
// testdata/TestExampleMyStructTabular/full_struct.golden
|
||||
//
|
||||
// Multiple Golden Files in a Single Test
|
||||
// # Multiple Golden Files in a Single Test
|
||||
//
|
||||
// The "P" suffixed methods, GetP(), SetP(), and FileP(), all take a name
|
||||
// The "P" suffixed methods, GetP(), SetP(), DoP(), and FileP(), all take a name
|
||||
// argument which allows using specific golden files within a given *testing.T
|
||||
// instance.
|
||||
//
|
||||
// func TestExampleMyStructP(t *testing.T) {
|
||||
// gotJSON, _ := json.Marshal(&MyStruct{Foo: "Bar"})
|
||||
// gotXML, _ := xml.Marshal(&MyStruct{Foo: "Bar"})
|
||||
// func TestExampleMyStructP(t *testing.T) {
|
||||
// gotJSON, _ := json.Marshal(&MyStruct{Foo: "Bar"})
|
||||
// gotXML, _ := xml.Marshal(&MyStruct{Foo: "Bar"})
|
||||
//
|
||||
// if golden.Update() {
|
||||
// golden.SetP(t, "json", gotJSON)
|
||||
// golden.SetP(t, "xml", gotXML)
|
||||
// }
|
||||
// wantJSON := golden.DoP(t, "json", gotJSON)
|
||||
// wantXML := golden.DoP(t, "xml", gotXML)
|
||||
//
|
||||
// assert.Equal(t, golden.GetP(t, "json"), gotJSON)
|
||||
// assert.Equal(t, golden.GetP(t, "xml"), gotXML)
|
||||
// }
|
||||
// assert.Equal(t, wantJSON, gotJSON)
|
||||
// assert.Equal(t, wantXML, gotXML)
|
||||
// }
|
||||
//
|
||||
// The above example will read/write to:
|
||||
//
|
||||
// testdata/TestExampleMyStructP/json.golden
|
||||
// testdata/TestExampleMyStructP/xml.golden
|
||||
// testdata/TestExampleMyStructP/json.golden
|
||||
// testdata/TestExampleMyStructP/xml.golden
|
||||
//
|
||||
// This works with tabular tests too of course:
|
||||
//
|
||||
// func TestExampleMyStructTabularP(t *testing.T) {
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// obj *MyStruct
|
||||
// }{
|
||||
// {name: "empty struct", obj: &MyStruct{}},
|
||||
// {name: "full struct", obj: &MyStruct{Foo: "Bar"}},
|
||||
// }
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// gotJSON, _ := json.Marshal(tt.obj)
|
||||
// gotXML, _ := xml.Marshal(tt.obj)
|
||||
// func TestExampleMyStructTabularP(t *testing.T) {
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// obj *MyStruct
|
||||
// }{
|
||||
// {name: "empty struct", obj: &MyStruct{}},
|
||||
// {name: "full struct", obj: &MyStruct{Foo: "Bar"}},
|
||||
// }
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// gotJSON, _ := json.Marshal(tt.obj)
|
||||
// gotXML, _ := xml.Marshal(tt.obj)
|
||||
//
|
||||
// if golden.Update() {
|
||||
// golden.SetP(t, "json", gotJSON)
|
||||
// golden.SetP(t, "xml", gotXML)
|
||||
// }
|
||||
// wantJSON := golden.DoP(t, "json", gotJSON)
|
||||
// wantXML := golden.DoP(t, "xml", gotXML)
|
||||
//
|
||||
// assert.Equal(t, golden.GetP(t, "json"), gotJSON)
|
||||
// assert.Equal(t, golden.GetP(t, "xml"), gotXML)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// assert.Equal(t, wantJSON, gotJSON)
|
||||
// assert.Equal(t, wantXML, gotXML)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// The above example will read/write to:
|
||||
//
|
||||
// testdata/TestExampleMyStructTabularP/empty_struct/json.golden
|
||||
// testdata/TestExampleMyStructTabularP/empty_struct/xml.golden
|
||||
// testdata/TestExampleMyStructTabularP/full_struct/json.golden
|
||||
// testdata/TestExampleMyStructTabularP/full_struct/xml.golden
|
||||
//
|
||||
// testdata/TestExampleMyStructTabularP/empty_struct/json.golden
|
||||
// testdata/TestExampleMyStructTabularP/empty_struct/xml.golden
|
||||
// testdata/TestExampleMyStructTabularP/full_struct/json.golden
|
||||
// testdata/TestExampleMyStructTabularP/full_struct/xml.golden
|
||||
package golden
|
||||
|
||||
import (
|
||||
@@ -132,12 +128,11 @@ import (
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
//go:generate mockgen -source=golden.go -destination=golden_mock_test.go -package golden -self_package github.com/jimeh/go-golden
|
||||
|
||||
// TestingT is a interface describing a sub-set of methods of *testing.T which
|
||||
// golden uses.
|
||||
type TestingT interface {
|
||||
Error(args ...interface{})
|
||||
Errorf(format string, args ...interface{})
|
||||
FailNow()
|
||||
Fatal(args ...interface{})
|
||||
Fatalf(format string, args ...interface{})
|
||||
Helper()
|
||||
@@ -146,23 +141,25 @@ type TestingT interface {
|
||||
Name() string
|
||||
}
|
||||
|
||||
var defaultGolden = New()
|
||||
// Default is the default Golden instance used by all top-level package
|
||||
// functions.
|
||||
var Default = New()
|
||||
|
||||
// File returns the filename of the golden file for the given *testing.T
|
||||
// instance as determined by t.Name().
|
||||
func File(t *testing.T) string {
|
||||
func File(t TestingT) string {
|
||||
t.Helper()
|
||||
|
||||
return defaultGolden.File(t)
|
||||
return Default.File(t)
|
||||
}
|
||||
|
||||
// Get returns the content of the golden file for the given *testing.T instance
|
||||
// as determined by t.Name(). If no golden file can be found/read, it will fail
|
||||
// the test by calling t.Fatal().
|
||||
func Get(t *testing.T) []byte {
|
||||
func Get(t TestingT) []byte {
|
||||
t.Helper()
|
||||
|
||||
return defaultGolden.Get(t)
|
||||
return Default.Get(t)
|
||||
}
|
||||
|
||||
// Set writes given data to the golden file for the given *testing.T instance as
|
||||
@@ -171,15 +168,24 @@ func Get(t *testing.T) []byte {
|
||||
func Set(t *testing.T, data []byte) {
|
||||
t.Helper()
|
||||
|
||||
defaultGolden.Set(t, data)
|
||||
Default.Set(t, data)
|
||||
}
|
||||
|
||||
// Do is a convenience function for calling Update(), Set(), and Get() in a
|
||||
// single call. If Update() returns true, data will be written to the golden
|
||||
// file using Set(), before reading it back with Get().
|
||||
func Do(t TestingT, data []byte) []byte {
|
||||
t.Helper()
|
||||
|
||||
return Default.Do(t, data)
|
||||
}
|
||||
|
||||
// FileP returns the filename of the specifically named golden file for the
|
||||
// given *testing.T instance as determined by t.Name().
|
||||
func FileP(t *testing.T, name string) string {
|
||||
func FileP(t TestingT, name string) string {
|
||||
t.Helper()
|
||||
|
||||
return defaultGolden.FileP(t, name)
|
||||
return Default.FileP(t, name)
|
||||
}
|
||||
|
||||
// GetP returns the content of the specifically named golden file belonging
|
||||
@@ -191,7 +197,7 @@ func FileP(t *testing.T, name string) string {
|
||||
func GetP(t *testing.T, name string) []byte {
|
||||
t.Helper()
|
||||
|
||||
return defaultGolden.GetP(t, name)
|
||||
return Default.GetP(t, name)
|
||||
}
|
||||
|
||||
// SetP writes given data of the specifically named golden file belonging to
|
||||
@@ -203,7 +209,16 @@ func GetP(t *testing.T, name string) []byte {
|
||||
func SetP(t *testing.T, name string, data []byte) {
|
||||
t.Helper()
|
||||
|
||||
defaultGolden.SetP(t, name, data)
|
||||
Default.SetP(t, name, data)
|
||||
}
|
||||
|
||||
// DoP is a convenience function for calling Update(), SetP(), and GetP() in a
|
||||
// single call. If Update() returns true, data will be written to the golden
|
||||
// file using SetP(), before reading it back with GetP().
|
||||
func DoP(t TestingT, name string, data []byte) []byte {
|
||||
t.Helper()
|
||||
|
||||
return Default.DoP(t, name, data)
|
||||
}
|
||||
|
||||
// Update returns true when golden is set to update golden files. Should be used
|
||||
@@ -213,7 +228,7 @@ func SetP(t *testing.T, name string, data []byte) {
|
||||
// environment variable is set to a truthy value. To customize create a custom
|
||||
// *Golden instance with New() and set a new UpdateFunc value.
|
||||
func Update() bool {
|
||||
return defaultGolden.Update()
|
||||
return Default.Update()
|
||||
}
|
||||
|
||||
// Golden handles all interactions with golden files. The top-level package
|
||||
@@ -233,6 +248,11 @@ type Golden interface {
|
||||
// test by calling t.Fatal() with error details.
|
||||
Set(t TestingT, data []byte)
|
||||
|
||||
// Do is a convenience function for calling Update(), Set(), and Get() in a
|
||||
// single call. If Update() returns true, data will be written to the golden
|
||||
// file using Set(), before reading it back with Get().
|
||||
Do(t TestingT, data []byte) []byte
|
||||
|
||||
// FileP returns the filename of the specifically named golden file for the
|
||||
// given TestingT instance as determined by t.Name().
|
||||
FileP(t TestingT, name string) string
|
||||
@@ -253,6 +273,11 @@ type Golden interface {
|
||||
// files to be used within the same one TestingT instance.
|
||||
SetP(t TestingT, name string, data []byte)
|
||||
|
||||
// DoP is a convenience function for calling Update(), SetP(), and GetP() in
|
||||
// a single call. If Update() returns true, data will be written to the
|
||||
// golden file using SetP(), before reading it back with GetP().
|
||||
DoP(t TestingT, name string, data []byte) []byte
|
||||
|
||||
// Update returns true when golden is set to update golden files. Should be
|
||||
// used to determine if golden.Set() or golden.SetP() should be called or
|
||||
// not.
|
||||
@@ -342,7 +367,8 @@ func WithUpdateFunc(fn UpdateFunc) Option {
|
||||
})
|
||||
}
|
||||
|
||||
// WithFs sets s afero.Fs instance which is used to read/write all golden files.
|
||||
// WithFs sets the afero.Fs instance which is used for all file system
|
||||
// operations to read/write golden files.
|
||||
//
|
||||
// When this option is not provided, the default value is afero.NewOsFs().
|
||||
func WithFs(fs afero.Fs) Option {
|
||||
@@ -394,55 +420,75 @@ type golden struct {
|
||||
// Ensure golden satisfies Golden interface.
|
||||
var _ Golden = &golden{}
|
||||
|
||||
func (s *golden) File(t TestingT) string {
|
||||
func (g *golden) File(t TestingT) string {
|
||||
t.Helper()
|
||||
|
||||
return s.file(t, "")
|
||||
return g.file(t, "")
|
||||
}
|
||||
|
||||
func (s *golden) Get(t TestingT) []byte {
|
||||
func (g *golden) Get(t TestingT) []byte {
|
||||
t.Helper()
|
||||
|
||||
return s.get(t, "")
|
||||
return g.get(t, "")
|
||||
}
|
||||
|
||||
func (s *golden) Set(t TestingT, data []byte) {
|
||||
func (g *golden) Set(t TestingT, data []byte) {
|
||||
t.Helper()
|
||||
|
||||
s.set(t, "", data)
|
||||
g.set(t, "", data)
|
||||
}
|
||||
|
||||
func (s *golden) FileP(t TestingT, name string) string {
|
||||
func (g *golden) Do(t TestingT, data []byte) []byte {
|
||||
t.Helper()
|
||||
|
||||
if g.Update() {
|
||||
g.Set(t, data)
|
||||
}
|
||||
|
||||
return g.Get(t)
|
||||
}
|
||||
|
||||
func (g *golden) FileP(t TestingT, name string) string {
|
||||
t.Helper()
|
||||
|
||||
if name == "" {
|
||||
t.Fatalf("golden: test name cannot be empty")
|
||||
}
|
||||
|
||||
return s.file(t, name)
|
||||
return g.file(t, name)
|
||||
}
|
||||
|
||||
func (s *golden) GetP(t TestingT, name string) []byte {
|
||||
func (g *golden) GetP(t TestingT, name string) []byte {
|
||||
t.Helper()
|
||||
|
||||
if name == "" {
|
||||
t.Fatal("golden: name cannot be empty")
|
||||
}
|
||||
|
||||
return s.get(t, name)
|
||||
return g.get(t, name)
|
||||
}
|
||||
|
||||
func (s *golden) SetP(t TestingT, name string, data []byte) {
|
||||
func (g *golden) SetP(t TestingT, name string, data []byte) {
|
||||
t.Helper()
|
||||
|
||||
if name == "" {
|
||||
t.Fatal("golden: name cannot be empty")
|
||||
}
|
||||
|
||||
s.set(t, name, data)
|
||||
g.set(t, name, data)
|
||||
}
|
||||
|
||||
func (s *golden) file(t TestingT, name string) string {
|
||||
func (g *golden) DoP(t TestingT, name string, data []byte) []byte {
|
||||
t.Helper()
|
||||
|
||||
if g.Update() {
|
||||
g.SetP(t, name, data)
|
||||
}
|
||||
|
||||
return g.GetP(t, name)
|
||||
}
|
||||
|
||||
func (g *golden) file(t TestingT, name string) string {
|
||||
t.Helper()
|
||||
|
||||
if t.Name() == "" {
|
||||
@@ -451,12 +497,12 @@ func (s *golden) file(t TestingT, name string) string {
|
||||
)
|
||||
}
|
||||
|
||||
base := []string{s.dirname, filepath.FromSlash(t.Name())}
|
||||
base := []string{g.dirname, filepath.FromSlash(t.Name())}
|
||||
if name != "" {
|
||||
base = append(base, name)
|
||||
}
|
||||
|
||||
f := filepath.Clean(filepath.Join(base...) + s.suffix)
|
||||
f := filepath.Clean(filepath.Join(base...) + g.suffix)
|
||||
|
||||
dirty := strings.Split(f, string(os.PathSeparator))
|
||||
clean := make([]string, 0, len(dirty))
|
||||
@@ -467,12 +513,12 @@ func (s *golden) file(t TestingT, name string) string {
|
||||
return strings.Join(clean, string(os.PathSeparator))
|
||||
}
|
||||
|
||||
func (s *golden) get(t TestingT, name string) []byte {
|
||||
func (g *golden) get(t TestingT, name string) []byte {
|
||||
t.Helper()
|
||||
|
||||
f := s.file(t, name)
|
||||
f := g.file(t, name)
|
||||
|
||||
b, err := afero.ReadFile(s.fs, f)
|
||||
b, err := afero.ReadFile(g.fs, f)
|
||||
if err != nil {
|
||||
t.Fatalf("golden: %s", err.Error())
|
||||
}
|
||||
@@ -480,27 +526,27 @@ func (s *golden) get(t TestingT, name string) []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
func (s *golden) set(t TestingT, name string, data []byte) {
|
||||
func (g *golden) set(t TestingT, name string, data []byte) {
|
||||
t.Helper()
|
||||
|
||||
f := s.file(t, name)
|
||||
f := g.file(t, name)
|
||||
dir := filepath.Dir(f)
|
||||
|
||||
if s.logOnWrite {
|
||||
if g.logOnWrite {
|
||||
t.Logf("golden: writing golden file: %s", f)
|
||||
}
|
||||
|
||||
err := s.fs.MkdirAll(dir, s.dirMode)
|
||||
err := g.fs.MkdirAll(dir, g.dirMode)
|
||||
if err != nil {
|
||||
t.Fatalf("golden: failed to create directory: %s", err.Error())
|
||||
}
|
||||
|
||||
err = afero.WriteFile(s.fs, f, data, s.fileMode)
|
||||
err = afero.WriteFile(g.fs, f, data, g.fileMode)
|
||||
if err != nil {
|
||||
t.Fatalf("golden: filed to write file: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *golden) Update() bool {
|
||||
return s.updateFunc()
|
||||
func (g *golden) Update() bool {
|
||||
return g.updateFunc()
|
||||
}
|
||||
|
||||
306
golden_mock_test.go
Normal file
306
golden_mock_test.go
Normal file
@@ -0,0 +1,306 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: golden.go
|
||||
|
||||
// Package golden is a generated GoMock package.
|
||||
package golden
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockTestingT is a mock of TestingT interface.
|
||||
type MockTestingT struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockTestingTMockRecorder
|
||||
}
|
||||
|
||||
// MockTestingTMockRecorder is the mock recorder for MockTestingT.
|
||||
type MockTestingTMockRecorder struct {
|
||||
mock *MockTestingT
|
||||
}
|
||||
|
||||
// NewMockTestingT creates a new mock instance.
|
||||
func NewMockTestingT(ctrl *gomock.Controller) *MockTestingT {
|
||||
mock := &MockTestingT{ctrl: ctrl}
|
||||
mock.recorder = &MockTestingTMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockTestingT) EXPECT() *MockTestingTMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Fatal mocks base method.
|
||||
func (m *MockTestingT) Fatal(args ...interface{}) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{}
|
||||
for _, a := range args {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
m.ctrl.Call(m, "Fatal", varargs...)
|
||||
}
|
||||
|
||||
// Fatal indicates an expected call of Fatal.
|
||||
func (mr *MockTestingTMockRecorder) Fatal(args ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fatal", reflect.TypeOf((*MockTestingT)(nil).Fatal), args...)
|
||||
}
|
||||
|
||||
// Fatalf mocks base method.
|
||||
func (m *MockTestingT) Fatalf(format string, args ...interface{}) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{format}
|
||||
for _, a := range args {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
m.ctrl.Call(m, "Fatalf", varargs...)
|
||||
}
|
||||
|
||||
// Fatalf indicates an expected call of Fatalf.
|
||||
func (mr *MockTestingTMockRecorder) Fatalf(format interface{}, args ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{format}, args...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fatalf", reflect.TypeOf((*MockTestingT)(nil).Fatalf), varargs...)
|
||||
}
|
||||
|
||||
// Helper mocks base method.
|
||||
func (m *MockTestingT) Helper() {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Helper")
|
||||
}
|
||||
|
||||
// Helper indicates an expected call of Helper.
|
||||
func (mr *MockTestingTMockRecorder) Helper() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Helper", reflect.TypeOf((*MockTestingT)(nil).Helper))
|
||||
}
|
||||
|
||||
// Log mocks base method.
|
||||
func (m *MockTestingT) Log(args ...interface{}) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{}
|
||||
for _, a := range args {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
m.ctrl.Call(m, "Log", varargs...)
|
||||
}
|
||||
|
||||
// Log indicates an expected call of Log.
|
||||
func (mr *MockTestingTMockRecorder) Log(args ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Log", reflect.TypeOf((*MockTestingT)(nil).Log), args...)
|
||||
}
|
||||
|
||||
// Logf mocks base method.
|
||||
func (m *MockTestingT) Logf(format string, args ...interface{}) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{format}
|
||||
for _, a := range args {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
m.ctrl.Call(m, "Logf", varargs...)
|
||||
}
|
||||
|
||||
// Logf indicates an expected call of Logf.
|
||||
func (mr *MockTestingTMockRecorder) Logf(format interface{}, args ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{format}, args...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Logf", reflect.TypeOf((*MockTestingT)(nil).Logf), varargs...)
|
||||
}
|
||||
|
||||
// Name mocks base method.
|
||||
func (m *MockTestingT) Name() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Name")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Name indicates an expected call of Name.
|
||||
func (mr *MockTestingTMockRecorder) Name() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockTestingT)(nil).Name))
|
||||
}
|
||||
|
||||
// MockGolden is a mock of Golden interface.
|
||||
type MockGolden struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockGoldenMockRecorder
|
||||
}
|
||||
|
||||
// MockGoldenMockRecorder is the mock recorder for MockGolden.
|
||||
type MockGoldenMockRecorder struct {
|
||||
mock *MockGolden
|
||||
}
|
||||
|
||||
// NewMockGolden creates a new mock instance.
|
||||
func NewMockGolden(ctrl *gomock.Controller) *MockGolden {
|
||||
mock := &MockGolden{ctrl: ctrl}
|
||||
mock.recorder = &MockGoldenMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockGolden) EXPECT() *MockGoldenMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Do mocks base method.
|
||||
func (m *MockGolden) Do(t TestingT, data []byte) []byte {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Do", t, data)
|
||||
ret0, _ := ret[0].([]byte)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Do indicates an expected call of Do.
|
||||
func (mr *MockGoldenMockRecorder) Do(t, data interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Do", reflect.TypeOf((*MockGolden)(nil).Do), t, data)
|
||||
}
|
||||
|
||||
// DoP mocks base method.
|
||||
func (m *MockGolden) DoP(t TestingT, name string, data []byte) []byte {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DoP", t, name, data)
|
||||
ret0, _ := ret[0].([]byte)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DoP indicates an expected call of DoP.
|
||||
func (mr *MockGoldenMockRecorder) DoP(t, name, data interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DoP", reflect.TypeOf((*MockGolden)(nil).DoP), t, name, data)
|
||||
}
|
||||
|
||||
// File mocks base method.
|
||||
func (m *MockGolden) File(t TestingT) string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "File", t)
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// File indicates an expected call of File.
|
||||
func (mr *MockGoldenMockRecorder) File(t interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "File", reflect.TypeOf((*MockGolden)(nil).File), t)
|
||||
}
|
||||
|
||||
// FileP mocks base method.
|
||||
func (m *MockGolden) FileP(t TestingT, name string) string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "FileP", t, name)
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// FileP indicates an expected call of FileP.
|
||||
func (mr *MockGoldenMockRecorder) FileP(t, name interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FileP", reflect.TypeOf((*MockGolden)(nil).FileP), t, name)
|
||||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockGolden) Get(t TestingT) []byte {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", t)
|
||||
ret0, _ := ret[0].([]byte)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockGoldenMockRecorder) Get(t interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockGolden)(nil).Get), t)
|
||||
}
|
||||
|
||||
// GetP mocks base method.
|
||||
func (m *MockGolden) GetP(t TestingT, name string) []byte {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetP", t, name)
|
||||
ret0, _ := ret[0].([]byte)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetP indicates an expected call of GetP.
|
||||
func (mr *MockGoldenMockRecorder) GetP(t, name interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetP", reflect.TypeOf((*MockGolden)(nil).GetP), t, name)
|
||||
}
|
||||
|
||||
// Set mocks base method.
|
||||
func (m *MockGolden) Set(t TestingT, data []byte) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Set", t, data)
|
||||
}
|
||||
|
||||
// Set indicates an expected call of Set.
|
||||
func (mr *MockGoldenMockRecorder) Set(t, data interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockGolden)(nil).Set), t, data)
|
||||
}
|
||||
|
||||
// SetP mocks base method.
|
||||
func (m *MockGolden) SetP(t TestingT, name string, data []byte) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetP", t, name, data)
|
||||
}
|
||||
|
||||
// SetP indicates an expected call of SetP.
|
||||
func (mr *MockGoldenMockRecorder) SetP(t, name, data interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetP", reflect.TypeOf((*MockGolden)(nil).SetP), t, name, data)
|
||||
}
|
||||
|
||||
// Update mocks base method.
|
||||
func (m *MockGolden) Update() bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Update")
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Update indicates an expected call of Update.
|
||||
func (mr *MockGoldenMockRecorder) Update() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockGolden)(nil).Update))
|
||||
}
|
||||
|
||||
// MockOption is a mock of Option interface.
|
||||
type MockOption struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockOptionMockRecorder
|
||||
}
|
||||
|
||||
// MockOptionMockRecorder is the mock recorder for MockOption.
|
||||
type MockOptionMockRecorder struct {
|
||||
mock *MockOption
|
||||
}
|
||||
|
||||
// NewMockOption creates a new mock instance.
|
||||
func NewMockOption(ctrl *gomock.Controller) *MockOption {
|
||||
mock := &MockOption{ctrl: ctrl}
|
||||
mock.recorder = &MockOptionMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockOption) EXPECT() *MockOptionMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// apply mocks base method.
|
||||
func (m *MockOption) apply(arg0 *golden) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "apply", arg0)
|
||||
}
|
||||
|
||||
// apply indicates an expected call of apply.
|
||||
func (mr *MockOptionMockRecorder) apply(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "apply", reflect.TypeOf((*MockOption)(nil).apply), arg0)
|
||||
}
|
||||
213
golden_test.go
213
golden_test.go
@@ -1,6 +1,7 @@
|
||||
package golden
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/jimeh/envctl"
|
||||
"github.com/jimeh/go-mocktesting"
|
||||
"github.com/spf13/afero"
|
||||
@@ -19,113 +21,68 @@ func stringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
func funcID(f interface{}) string {
|
||||
return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
|
||||
}
|
||||
|
||||
func setupDefaultMock(
|
||||
t *testing.T,
|
||||
ctrl *gomock.Controller,
|
||||
) (*MockTestingT, *MockGolden) {
|
||||
t.Helper()
|
||||
|
||||
mt := NewMockTestingT(ctrl)
|
||||
mg := NewMockGolden(ctrl)
|
||||
|
||||
originalDefault := Default
|
||||
Default = mg
|
||||
t.Cleanup(func() {
|
||||
Default = originalDefault
|
||||
})
|
||||
|
||||
return mt, mg
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
require.IsType(t, &golden{}, Default)
|
||||
|
||||
dg := Default.(*golden)
|
||||
|
||||
assert.Equal(t, fs.FileMode(0o755), dg.dirMode)
|
||||
assert.Equal(t, fs.FileMode(0o644), dg.fileMode)
|
||||
assert.Equal(t, ".golden", dg.suffix)
|
||||
assert.Equal(t, "testdata", dg.dirname)
|
||||
assert.Equal(t, funcID(EnvUpdateFunc), funcID(dg.updateFunc))
|
||||
assert.Equal(t, afero.NewOsFs(), dg.fs)
|
||||
assert.Equal(t, true, dg.logOnWrite)
|
||||
}
|
||||
|
||||
func TestFile(t *testing.T) {
|
||||
got := File(t)
|
||||
ctrl := gomock.NewController(t)
|
||||
mt, mg := setupDefaultMock(t, ctrl)
|
||||
|
||||
assert.Equal(t, filepath.Join("testdata", "TestFile.golden"), got)
|
||||
want := filepath.Join("testdata", t.Name()+".golden")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "",
|
||||
want: filepath.Join("testdata", "TestFile", "#00.golden"),
|
||||
},
|
||||
{
|
||||
name: "foobar",
|
||||
want: filepath.Join("testdata", "TestFile", "foobar.golden"),
|
||||
},
|
||||
{
|
||||
name: "foo/bar",
|
||||
want: filepath.Join("testdata", "TestFile", "foo", "bar.golden"),
|
||||
},
|
||||
{
|
||||
name: `"foobar"`,
|
||||
want: filepath.Join("testdata", "TestFile", "_foobar_.golden"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := File(t)
|
||||
mt.EXPECT().Helper()
|
||||
mg.EXPECT().File(mt).Return(want)
|
||||
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
got := File(mt)
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
err := os.RemoveAll(filepath.Join("testdata", "TestGet"))
|
||||
require.NoError(t, err)
|
||||
err = os.Remove(filepath.Join("testdata", "TestGet.golden"))
|
||||
require.NoError(t, err)
|
||||
})
|
||||
ctrl := gomock.NewController(t)
|
||||
mt, mg := setupDefaultMock(t, ctrl)
|
||||
|
||||
err := os.MkdirAll("testdata", 0o755)
|
||||
require.NoError(t, err)
|
||||
want := []byte("foobar\nhello world :)")
|
||||
|
||||
content := []byte("foobar\nhello world :)")
|
||||
err = ioutil.WriteFile( //nolint:gosec
|
||||
filepath.Join("testdata", "TestGet.golden"), content, 0o644,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
mt.EXPECT().Helper()
|
||||
mg.EXPECT().Get(mt).Return(want)
|
||||
|
||||
got := Get(t)
|
||||
assert.Equal(t, content, got)
|
||||
got := Get(mt)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
file string
|
||||
want []byte
|
||||
}{
|
||||
{
|
||||
name: "",
|
||||
file: filepath.Join("testdata", "TestGet", "#00.golden"),
|
||||
want: []byte("number double-zero here"),
|
||||
},
|
||||
{
|
||||
name: "foobar",
|
||||
file: filepath.Join("testdata", "TestGet", "foobar.golden"),
|
||||
want: []byte("foobar here"),
|
||||
},
|
||||
{
|
||||
name: "foo/bar",
|
||||
file: filepath.Join("testdata", "TestGet", "foo", "bar.golden"),
|
||||
want: []byte("foo/bar style sub-sub-folders works too"),
|
||||
},
|
||||
{
|
||||
name: "john's lost flip-flop",
|
||||
file: filepath.Join(
|
||||
"testdata", "TestGet", "john's_lost_flip-flop.golden",
|
||||
),
|
||||
want: []byte("Did John lose his flip-flop again?"),
|
||||
},
|
||||
{
|
||||
name: "thing: it's a thing!",
|
||||
file: filepath.Join(
|
||||
"testdata", "TestGet", "thing__it's_a_thing!.golden",
|
||||
),
|
||||
want: []byte("A thing? Really? Are we getting lazy? :P"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
f := File(t)
|
||||
dir := filepath.Dir(f)
|
||||
|
||||
err := os.MkdirAll(dir, 0o755)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = ioutil.WriteFile(f, tt.want, 0o644) //nolint:gosec
|
||||
require.NoError(t, err)
|
||||
|
||||
got := Get(t)
|
||||
|
||||
assert.Equal(t, tt.file, f)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
@@ -196,54 +153,17 @@ func TestSet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFileP(t *testing.T) {
|
||||
got := FileP(t, "sub-name")
|
||||
assert.Equal(t,
|
||||
filepath.Join("testdata", "TestFileP", "sub-name.golden"), got,
|
||||
)
|
||||
ctrl := gomock.NewController(t)
|
||||
mt, mg := setupDefaultMock(t, ctrl)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
named string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "",
|
||||
named: "sub-thing",
|
||||
want: filepath.Join(
|
||||
"testdata", "TestFileP", "#00", "sub-thing.golden",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "fozbaz",
|
||||
named: "email",
|
||||
want: filepath.Join(
|
||||
"testdata", "TestFileP", "fozbaz", "email.golden",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "fozbaz",
|
||||
named: "json",
|
||||
want: filepath.Join(
|
||||
"testdata", "TestFileP", "fozbaz#01", "json.golden",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "foo/bar",
|
||||
named: "hello/world",
|
||||
want: filepath.Join(
|
||||
"testdata", "TestFileP",
|
||||
"foo", "bar",
|
||||
"hello", "world.golden",
|
||||
),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := FileP(t, tt.named)
|
||||
want := filepath.Join("testdata", t.Name(), "foobar.golden")
|
||||
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
mt.EXPECT().Helper()
|
||||
mg.EXPECT().FileP(mt, "foobar").Return(want)
|
||||
|
||||
got := FileP(mt, "foobar")
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestGetP(t *testing.T) {
|
||||
@@ -506,19 +426,12 @@ func TestNew(t *testing.T) {
|
||||
got, ok := g.(*golden)
|
||||
require.True(t, ok, "New did not returns a *golden instance")
|
||||
|
||||
gotUpdateFunc := runtime.FuncForPC(
|
||||
reflect.ValueOf(got.updateFunc).Pointer(),
|
||||
).Name()
|
||||
wantUpdateFunc := runtime.FuncForPC(
|
||||
reflect.ValueOf(tt.want.updateFunc).Pointer(),
|
||||
).Name()
|
||||
|
||||
assert.Equal(t, tt.want.dirMode, got.dirMode)
|
||||
assert.Equal(t, tt.want.fileMode, got.fileMode)
|
||||
assert.Equal(t, tt.want.suffix, got.suffix)
|
||||
assert.Equal(t, tt.want.dirname, got.dirname)
|
||||
assert.Equal(t, tt.want.logOnWrite, got.logOnWrite)
|
||||
assert.Equal(t, wantUpdateFunc, gotUpdateFunc)
|
||||
assert.Equal(t, funcID(tt.want.updateFunc), funcID(got.updateFunc))
|
||||
assert.IsType(t, tt.want.fs, got.fs)
|
||||
})
|
||||
}
|
||||
|
||||
20
update.go
20
update.go
@@ -1,6 +1,7 @@
|
||||
package golden
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
@@ -24,3 +25,22 @@ func EnvUpdateFunc() bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
updateFlagSet *flag.FlagSet
|
||||
updateFlag bool
|
||||
)
|
||||
|
||||
// UpdateFunc returns a function that checks a -update flag is set.
|
||||
func FlagUpdateFunc() bool {
|
||||
if updateFlagSet == nil {
|
||||
updateFlagSet = flag.NewFlagSet("golden", flag.ContinueOnError)
|
||||
updateFlagSet.BoolVar(&updateFlag,
|
||||
"update", false, "update golden files",
|
||||
)
|
||||
}
|
||||
|
||||
_ = updateFlagSet.Parse(os.Args[1:])
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user