feat(assert): use String() for Stringer types in diff output
Values whose type, or slice or array element type, implements fmt.Stringer are now rendered through their String method in the diff section of a failed assertion. Previously a named string such as peer.ID was dumped as raw escaped bytes, which is unreadable. This affects diff presentation only. Equality is still decided by ObjectsAreEqual and is unaffected. The default spew config keeps DisableMethods for every other type, matching the existing time.Time handling in diff. Refs #1215
This commit is contained in:
1 parent
08fef859fb
commit
9337ead2bc
2 files changed
+50
-2
No files matched your search
+26
-2
@@ -1955,8 +1955,13 @@ func diff(expected interface{}, actual interface{}) string {
|
||||
e = spewConfigStringerEnabled.Sdump(expected)
|
||||
a = spewConfigStringerEnabled.Sdump(actual)
|
||||
default:
|
||||
e = spewConfig.Sdump(expected)
|
||||
a = spewConfig.Sdump(actual)
|
||||
if hasStringer(et) {
|
||||
e = spewConfigStringerEnabled.Sdump(expected)
|
||||
a = spewConfigStringerEnabled.Sdump(actual)
|
||||
} else {
|
||||
e = spewConfig.Sdump(expected)
|
||||
a = spewConfig.Sdump(actual)
|
||||
}
|
||||
}
|
||||
|
||||
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
||||
@@ -1972,6 +1977,25 @@ func diff(expected interface{}, actual interface{}) string {
|
||||
return "\n\nDiff:\n" + diff
|
||||
}
|
||||
|
||||
var stringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
|
||||
|
||||
// hasStringer reports whether t, or the element type of a slice or array,
|
||||
// implements fmt.Stringer. It lets diff render such values through the
|
||||
// Stringer-enabled spew config, so a named string like peer.ID is shown by its
|
||||
// String output instead of its raw bytes. This influences diff presentation
|
||||
// only: equality is decided by ObjectsAreEqual and is unaffected, and the
|
||||
// default spew config keeps DisableMethods for every other type.
|
||||
func hasStringer(t reflect.Type) bool {
|
||||
if t.Implements(stringerType) {
|
||||
return true
|
||||
}
|
||||
switch t.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
return t.Elem().Implements(stringerType)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isFunction(arg interface{}) bool {
|
||||
if arg == nil {
|
||||
return false
|
||||
|
||||
@@ -2902,6 +2902,12 @@ func (d *diffTestingStruct) String() string {
|
||||
return d.A
|
||||
}
|
||||
|
||||
type diffTestingStringer string
|
||||
|
||||
func (id diffTestingStringer) String() string {
|
||||
return "stringer:" + string(id)
|
||||
}
|
||||
|
||||
func TestDiff(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -3036,6 +3042,24 @@ Diff:
|
||||
time.Date(2020, 9, 25, 0, 0, 0, 0, time.UTC),
|
||||
)
|
||||
Equal(t, expected, actual)
|
||||
|
||||
expected = `
|
||||
|
||||
Diff:
|
||||
--- Expected
|
||||
+++ Actual
|
||||
@@ -2,3 +2,3 @@
|
||||
(assert.diffTestingStringer) (len=3) stringer:one,
|
||||
- (assert.diffTestingStringer) (len=3) stringer:two
|
||||
+ (assert.diffTestingStringer) (len=5) stringer:three
|
||||
}
|
||||
`
|
||||
|
||||
actual = diff(
|
||||
[]diffTestingStringer{"one", "two"},
|
||||
[]diffTestingStringer{"one", "three"},
|
||||
)
|
||||
Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestTimeEqualityErrorFormatting(t *testing.T) {
|
||||
|
||||
Reference in new issue
Block a user