-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Is there a way, or a v2 plan to provide more user friendly ways of diffing values for large structs?
Two types I make use of a lot are times and money-friendly decimals, and this combined with needing to compare large structs results in...
Which is unreadable.
For simple cases I compare the .String() output like a.Equal(want.String(), got.String()) which is a little more typing but it's fine for single values.
The problem is when asserting structs that have many fields. I don't want to waste time pulling out all these fields into tons of assertions just so I can add .string() to each item.
Ideally, I'd like to satisfy some comparator interface for our custom money type so diffs and comparisons are done against the rendered value not the underlying data. One other detail of decimal values is different combinations of bases and exponents can result in the same actual number. Assertions fail on this even if the actual resulting number is the same.
type MonetaryValue struct {
Num decimal.Decimal `json:"num"` // The underlying value: 1234.69
Cur BaseCurrency `json:"cur"` // the currency identifier: USD
Fmt string `json:"fmt"` // the formatted value: $1,234.69
}
func (v MonetaryValue) GoString() string {
return fmt.Sprintf(`"%s" (%s, %f)`, v.Fmt, v.Cur, v.Num.InexactFloat64())
}
func (v MonetaryValue) String() string {
return v.Fmt
}I've already got this, which gets me slightly nicer diffs but the comparison is still conducted against the underlying struct data, which isn't helpful for this particular case.
What would be ideal is a simple test interface:
func (v MonetaryValue) TestCompare(against MonetaryValue) bool {
return v.Fmt == against.Fmt
}Or maybe a way to surface better diff strings too.
go-cmp kind of solves this but it's not across all tests via an interface, it's just for a single assert - which is cumbersome to add to every test when you have hundreds.
gt.DeepEqual(t, want, got, cmp.Transformer("MonetaryValue", func(in currency.MonetaryValue) string {
return in.Fmt
}))
