Skip to content

Commit

Permalink
fix: print value type for interface{} containers (#409)
Browse files Browse the repository at this point in the history
When a value is contained in an interface{} we should show the type of
the value as well as the interface{} type

Consider the test:

  Expect([]interface{}{1}).To(Equal([]interface{}{uint(1)}))

Previous message:

  Expected
    <[]interface {} | len:1, cap:1>: [1]
  to equal
    <[]interface {} | len:1, cap:1>: [1]

New message:

  Expected
    <[]interface {} | len:1, cap:1>: [<int>1]
  to equal
    <[]interface {} | len:1, cap:1>: [<uint>1]

By showing the type, it's much easier to work out what is going on
  • Loading branch information
blgm committed Feb 3, 2021
1 parent 1fa9468 commit f08e2dc
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 8 deletions.
6 changes: 5 additions & 1 deletion format/format.go
Expand Up @@ -271,7 +271,7 @@ func formatValue(value reflect.Value, indentation uint) string {
}
return formatStruct(value, indentation)
case reflect.Interface:
return formatValue(value.Elem(), indentation)
return formatInterface(value, indentation)
default:
if value.CanInterface() {
return fmt.Sprintf("%#v", value.Interface())
Expand Down Expand Up @@ -366,6 +366,10 @@ func formatStruct(v reflect.Value, indentation uint) string {
return fmt.Sprintf("{%s}", strings.Join(result, ", "))
}

func formatInterface(v reflect.Value, indentation uint) string {
return fmt.Sprintf("<%s>%s", formatType(v.Elem()), formatValue(v.Elem(), indentation))
}

func isNilValue(a reflect.Value) bool {
switch a.Kind() {
case reflect.Invalid:
Expand Down
24 changes: 21 additions & 3 deletions format/format_test.go
Expand Up @@ -95,7 +95,7 @@ var _ = Describe("Format", func() {
for i := range arr {
arr[i] = entriesSwitch
}
return "{" + strings.Join(arr, ", ") + "}"
return "{\\s*" + strings.Join(arr, ",\\s* ") + ",?\\s*}"
}

Describe("Message", func() {
Expand Down Expand Up @@ -526,6 +526,24 @@ var _ = Describe("Format", func() {
})
})

Describe("formatting nested interface{} types", func() {
It("should print out the types of the container and value", func() {
Expect(Object([]interface{}{"foo"}, 1)).
To(match("[]interface {} | len:1, cap:1", `[<string>"foo"]`))

Expect(Object(map[string]interface{}{"foo": true}, 1)).
To(match("map[string]interface {} | len:1", `{"foo": <bool>true}`))

Expect(Object(struct{ A interface{} }{A: 1}, 1)).
To(match("struct { A interface {} }", "{A: <int>1}"))

v := struct{ A interface{} }{A: struct{ B string }{B: "foo"}}
Expect(Object(v, 1)).To(match(`struct { A interface {} }`, `{
A: <struct { B string }>{B: "foo"},
}`))
})
})

Describe("formatting times", func() {
It("should format time as RFC3339", func() {
t := time.Date(2016, 10, 31, 9, 57, 23, 12345, time.UTC)
Expand Down Expand Up @@ -574,7 +592,7 @@ var _ = Describe("Format", func() {
byteArrValue: \[17, 20, 32\],
mapValue: %s,
structValue: {Exported: "exported"},
interfaceValue: {"a key": 17},
interfaceValue: <map\[string\]int \| len:1>{"a key": 17},
}`, s.chanValue, s.funcValue, hashMatchingRegexp(`"a key": 20`, `"b key": 30`))

Expect(Object(s, 1)).Should(matchRegexp(`format_test\.SecretiveStruct`, expected))
Expand All @@ -590,7 +608,7 @@ var _ = Describe("Format", func() {
outerHash["integer"] = 2
outerHash["map"] = innerHash

expected := hashMatchingRegexp(`"integer": 2`, `"map": {"inner": 3}`)
expected := hashMatchingRegexp(`"integer": <int>2`, `"map": <map\[string\]int \| len:1>{"inner": 3}`)
Expect(Object(outerHash, 1)).Should(matchRegexp(`map\[string\]interface {} \| len:2`, expected))
})
})
Expand Down
4 changes: 2 additions & 2 deletions matchers/consist_of_test.go
Expand Up @@ -160,7 +160,7 @@ the extra elements were
})

expected := `to consist of
\s*<\[\]interface {} \| len:2, cap:2>: \[1, "C"\]
\s*<\[\]interface {} \| len:2, cap:2>: \[<int>1, <string>"C"\]
the missing elements were
\s*<\[\]string \| len:1, cap:1>: \["C"\]
the extra elements were
Expand All @@ -173,7 +173,7 @@ the extra elements were
Expect([]interface{}{1, "B"}).NotTo(ConsistOf(1, "B"))
})

expected := `not to consist of\n\s*<\[\]interface {} \| len:2, cap:2>: \[1, "B"\]`
expected := `not to consist of\n\s*<\[\]interface {} \| len:2, cap:2>: \[<int>1, <string>"B"\]`
Expect(failures).To(ConsistOf(MatchRegexp(expected)))
})
})
Expand Down
4 changes: 2 additions & 2 deletions matchers/contain_elements_matcher_test.go
Expand Up @@ -133,7 +133,7 @@ the missing elements were
})

expected := `to contain elements
\s*<\[\]interface {} \| len:2, cap:2>: \[1, "C"\]
\s*<\[\]interface {} \| len:2, cap:2>: \[<int>1, <string>"C"\]
the missing elements were
\s*<\[\]string \| len:1, cap:1>: \["C"\]`
Expect(failures).To(ConsistOf(MatchRegexp(expected)))
Expand All @@ -144,7 +144,7 @@ the missing elements were
Expect([]interface{}{1, "B"}).NotTo(ContainElements(1, "B"))
})

expected := `not to contain elements\n\s*<\[\]interface {} \| len:2, cap:2>: \[1, "B"\]`
expected := `not to contain elements\n\s*<\[\]interface {} \| len:2, cap:2>: \[<int>1, <string>"B"\]`
Expect(failures).To(ConsistOf(MatchRegexp(expected)))
})
})
Expand Down

0 comments on commit f08e2dc

Please sign in to comment.