Skip to content

Custom assert equal comparator interface #1204

@Southclaws

Description

@Southclaws

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...

image

image

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
}))

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions