proposal: use a better printer/differencer for failed matches #265
Description
See also issue #233 which is related.
When a gomock call fails an expectation, if the argument is an interface
, the output, based on the %v
format character, is not terribly helpful, e.g.,
controller.go:150: Unexpected call to *jobs_mock.MockJobs.Insert([testproject 0xc0001f2420]) at …/jobs_mock.go:62 because:
Expected call at …/my_test.go:132 doesn't match the argument at index 1.
Got: &{0xc000206300 0xc00020c120 <nil> <nil> {0 map[]} [] []}
Want: is equal to &{0xc000206100 0xc0000f5020 <nil> <nil> {0 map[]} [] []}
This doesn't help isolate the problem, which is only visible to reflect.DeepEqual
and is not obvious to me, the viewer of the test results. (The problem from the above turned out to be two levels deep into an embedded struct.)
Please consider either or both of the following:
Pretty-print the values
This would involve changing the code in calls.go
to use a formatter other than %v
for Got
, and matchers's String
implementation to use the same on the embedded interface. e.g.,
- https://godoc.org/github.com/kylelemons/godebug/pretty
- https://godoc.org/github.com/davecgh/go-spew/spew
Print a diff of the values
This would involve adding a new Matcher
method, e.g., Explain
or MatchAndExplain
to be able to more thoroughly specify what happened. To preserve backwards incompatibility, this would be in a new interface, e.g.,
type Explainer interface {
// MatchAndExplain returns whether x is a match and why.
MatchAndExplain(x interface{}) (bool, string)
}
func (e eqMatcher) MatchAndExplain(x interface{}) (bool, string) {
negation := ""
diff := ""
match := e.Matches(x)
if !match {
negate = "not "
diff = fmt.Sprintf("\nGot: %v\nWant: %v\nDiff: %s", x, e.x, cmp.Diff(e.x, x))
}
return match, fmt.Sprintf("is %sequal to %v%s", negation, e.x, diff)
}
Then, in lieu of using Matcher.String
and explicit Got/Want errors in call.go
, rely on MatchAndExplain
to yield the deep difference.
- https://godoc.org/github.com/google/go-cmp/cmp,
- https://godoc.org/github.com/kylelemons/godebug/diff
I'm not familiar with a go built-in pretty printer, so I think either of these would require either extending a core library, or allowing an import to do pretty printing / diffing. Not sure how feasible that is.
This approach is modeled at least partly after the C++ Google Test Matchers's MatcherInterface
; many examples of implementations of which are in the Google Mock matchers.