mirror of
https://github.com/jimeh/go-golden.git
synced 2026-02-19 11:16:47 +00:00
Tests have started using github.com/jimeh/go-mocktesting which allows testing unhappy paths where t.Fatal() and related functions are called.
134 lines
3.7 KiB
Go
134 lines
3.7 KiB
Go
package golden
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
|
|
"github.com/jimeh/go-golden/sanitize"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type (
|
|
MarshalFunc func(interface{}) ([]byte, error)
|
|
UnmarshalFunc func([]byte, interface{}) error
|
|
)
|
|
|
|
// MarshalingAsserter allows building marshaling asserters by providing
|
|
// functions which marshal and unmarshal objects.
|
|
type MarshalingAsserter struct {
|
|
// Golden is the *Golden instance used to read/write golden files.
|
|
Golden Golden
|
|
|
|
// Name of the format the MarshalAsserter handles.
|
|
Format string
|
|
|
|
// GoldName is the name of the golden file used when marshaling. This is by
|
|
// default set based on Format using NewMarshalAsserter. For example if
|
|
// Format is set to "JSON", GoldName will be set to "marshaled_json" by
|
|
// default.
|
|
GoldName string
|
|
|
|
// MarshalFunc is the function used to marshal given objects.
|
|
MarshalFunc MarshalFunc
|
|
|
|
// UnmarshalFunc is the function used to unmarshal given objects.
|
|
UnmarshalFunc UnmarshalFunc
|
|
|
|
// NormalizeLineBreaks determines if Windows' CRLF (\r\n) and MacOS Classic
|
|
// CR (\r) line breaks are replaced with Unix's LF (\n) line breaks. This
|
|
// ensures marshaling assertions work across different platforms.
|
|
NormalizeLineBreaks bool
|
|
}
|
|
|
|
// New returns a new MarshalingAsserter.
|
|
func NewMarshalingAsserter(
|
|
golden Golden,
|
|
format string,
|
|
marshalFunc MarshalFunc,
|
|
unmarshalFunc UnmarshalFunc,
|
|
normalizeLineBreaks bool,
|
|
) *MarshalingAsserter {
|
|
goldName := "marshaled_" + strings.ToLower(sanitize.Filename(format))
|
|
|
|
return &MarshalingAsserter{
|
|
Golden: golden,
|
|
Format: format,
|
|
GoldName: goldName,
|
|
MarshalFunc: marshalFunc,
|
|
UnmarshalFunc: unmarshalFunc,
|
|
NormalizeLineBreaks: normalizeLineBreaks,
|
|
}
|
|
}
|
|
|
|
// Marshaling asserts that the given "v" value marshals via the provided encoder
|
|
// to an expected value fetched from a golden file on disk, and then verifies
|
|
// that the marshaled result produces a value that is equal to "v" when
|
|
// unmarshaled.
|
|
//
|
|
// Used for objects that do NOT change when they are marshaled and unmarshaled.
|
|
func (s *MarshalingAsserter) Marshaling(t TestingT, v interface{}) {
|
|
t.Helper()
|
|
|
|
s.MarshalingP(t, v, v)
|
|
}
|
|
|
|
// MarshalingP asserts that the given "v" value marshals via the provided
|
|
// encoder to an expected value fetched from a golden file on disk, and then
|
|
// verifies that the marshaled result produces a value that is equal to "want"
|
|
// when unmarshaled.
|
|
//
|
|
// Used for objects that change when they are marshaled and unmarshaled.
|
|
func (s *MarshalingAsserter) MarshalingP(
|
|
t TestingT,
|
|
v interface{},
|
|
want interface{},
|
|
) {
|
|
t.Helper()
|
|
|
|
if reflect.ValueOf(want).Kind() != reflect.Ptr {
|
|
require.FailNowf(t,
|
|
"golden: only pointer types can be asserted",
|
|
"%T is not a pointer type", want,
|
|
)
|
|
}
|
|
|
|
marshaled, err := s.MarshalFunc(v)
|
|
require.NoErrorf(t,
|
|
err, "golden: failed to %s marshal %T: %+v", s.Format, v, v,
|
|
)
|
|
if s.NormalizeLineBreaks {
|
|
marshaled = sanitize.LineBreaks(marshaled)
|
|
}
|
|
|
|
if s.Golden.Update() {
|
|
s.Golden.SetP(t, s.GoldName, marshaled)
|
|
}
|
|
|
|
gold := s.Golden.GetP(t, s.GoldName)
|
|
if s.NormalizeLineBreaks {
|
|
gold = sanitize.LineBreaks(gold)
|
|
}
|
|
|
|
switch strings.ToLower(s.Format) {
|
|
case "json":
|
|
assert.JSONEq(t, string(gold), string(marshaled))
|
|
case "yaml", "yml":
|
|
assert.YAMLEq(t, string(gold), string(marshaled))
|
|
default:
|
|
assert.Equal(t, string(gold), string(marshaled))
|
|
}
|
|
|
|
got := reflect.New(reflect.TypeOf(want).Elem()).Interface()
|
|
err = s.UnmarshalFunc(gold, got)
|
|
|
|
f := s.Golden.FileP(t, s.GoldName)
|
|
require.NoErrorf(t, err,
|
|
"golden: failed to %s unmarshal %T from %s", s.Format, got, f,
|
|
)
|
|
assert.Equalf(t, want, got,
|
|
"golden: unmarshaling from golden file does not match "+
|
|
"expected object; golden file: %s", f,
|
|
)
|
|
}
|