-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
The naive string representation of an object is not always a helpful descriptive label for it when it appears in a failed assertion or requirement, and trailing messages (usually msgAndArgs
) are harder to parse visually than the main string block of an error message. Therefore, add a class of assertion methods which allow a wrapper to be applied.
Concrete example: I frequently work with protocol buffers which include status enums, and want to assert the expected status, e.g.
assert.Equal(t, pb.Status_VALID, resp.GetStatus())
When this fails, it gives this message:
Error: Not equal:
expected: 2
actual : 1
Test: TestCreationFooBar/create_asset
Protobuf enums have a .String()
method to retrieve their names, so obviously, I can change the assert to
assert.Equal(t, pb.Status_VALID.String(), resp.GetStatus().String())
and that will make the message
Error: Not equal:
expected: "VALID"
actual : "IN_PROGRESS"
Test: TestCreationFooBar/create_asset
This is much easier to read, and to distinguish from a slice with the wrong length or whatever, but it's a more brittle comparison - the integer comparison is the canonical one, it's just not human-legible.
The obvious way to get around this problem is to have variant types assert.EqualWithWrapper
, assert.ElementsMatchWithWrapper
, etc. which accept a func(x interface{})string
which is applied to the elements being compared before being combined into the error message. The one I'd use here, which would probably be fairly typical, might be func(x Stringable) { return fmt.Sprintf("%v [%s]", x, x.String()) }
.
I'm not sure how many methods of the API would benefit from having this equivalent. Equal
, EqualValues
, Exactly
, and NotEqual
seem obvious; ElementsMatch
, Contains
/NotContains
, and Subset
/NotSubset
also seem like they'd benefit. Many others might but it'd be niche, like WithinRange
; others like Implements
would require a more-complicated type signature (and would still probably be niche). There's clearly a steep tradeoff of API verbosity for this functionality, which isn't ideal, but I think it's worth doing at least in some cases.