Skip to content

Commit 2f8b16d

Browse files
committed
Truncate very long objects in test failure messages
1 parent 7f48972 commit 2f8b16d

File tree

2 files changed

+293
-49
lines changed

2 files changed

+293
-49
lines changed

assert/assertions.go

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,15 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
307307
func indentMessageLines(message string, longestLabelLen int) string {
308308
outBuf := new(bytes.Buffer)
309309

310-
for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
311-
// no need to align first line because it starts at the correct location (after the label)
312-
if i != 0 {
313-
// append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
314-
outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
310+
scanner := bufio.NewScanner(strings.NewReader(message))
311+
for firstLine := true; scanner.Scan(); firstLine = false {
312+
if !firstLine {
313+
fmt.Fprint(outBuf, "\n\t"+strings.Repeat(" ", longestLabelLen+1)+"\t")
315314
}
316-
outBuf.WriteString(scanner.Text())
315+
fmt.Fprint(outBuf, scanner.Text())
316+
}
317+
if err := scanner.Err(); err != nil {
318+
return fmt.Sprintf("cannot display message: %s", err)
317319
}
318320

319321
return outBuf.String()
@@ -504,8 +506,8 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b
504506

505507
if !samePointers(expected, actual) {
506508
return Fail(t, fmt.Sprintf("Not same: \n"+
507-
"expected: %p %#v\n"+
508-
"actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
509+
"expected: %p %s\n"+
510+
"actual : %p %s", expected, truncatingFormat("%#v", expected), actual, truncatingFormat("%#v", actual)), msgAndArgs...)
509511
}
510512

511513
return true
@@ -524,8 +526,8 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
524526

525527
if samePointers(expected, actual) {
526528
return Fail(t, fmt.Sprintf(
527-
"Expected and actual point to the same object: %p %#v",
528-
expected, expected), msgAndArgs...)
529+
"Expected and actual point to the same object: %p %s",
530+
expected, truncatingFormat("%#v", expected)), msgAndArgs...)
529531
}
530532
return true
531533
}
@@ -555,23 +557,24 @@ func samePointers(first, second interface{}) bool {
555557
// to a type conversion in the Go grammar.
556558
func formatUnequalValues(expected, actual interface{}) (e string, a string) {
557559
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
558-
return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)),
559-
fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual))
560+
return fmt.Sprintf("%T(%s)", expected, truncatingFormat("%#v", expected)),
561+
fmt.Sprintf("%T(%s)", actual, truncatingFormat("%#v", actual))
560562
}
561563
switch expected.(type) {
562564
case time.Duration:
563565
return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)
564566
}
565-
return truncatingFormat(expected), truncatingFormat(actual)
567+
return truncatingFormat("%#v", expected), truncatingFormat("%#v", actual)
566568
}
567569

568570
// truncatingFormat formats the data and truncates it if it's too long.
569571
//
570572
// This helps keep formatted error messages lines from exceeding the
571573
// bufio.MaxScanTokenSize max line length that the go testing framework imposes.
572-
func truncatingFormat(data interface{}) string {
573-
value := fmt.Sprintf("%#v", data)
574-
max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed.
574+
func truncatingFormat(format string, data interface{}) string {
575+
value := fmt.Sprintf(format, data)
576+
// Give us space for two truncated objects and the surrounding sentence.
577+
max := bufio.MaxScanTokenSize/2 - 100
575578
if len(value) > max {
576579
value = value[0:max] + "<... truncated>"
577580
}
@@ -711,7 +714,7 @@ func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
711714
if h, ok := t.(tHelper); ok {
712715
h.Helper()
713716
}
714-
return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
717+
return Fail(t, fmt.Sprintf("Expected nil, but got: %s", truncatingFormat("%#v", object)), msgAndArgs...)
715718
}
716719

717720
// isEmpty gets whether the specified object is considered empty or not.
@@ -753,7 +756,7 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
753756
if h, ok := t.(tHelper); ok {
754757
h.Helper()
755758
}
756-
Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
759+
Fail(t, fmt.Sprintf("Should be empty, but was %s", truncatingFormat("%v", object)), msgAndArgs...)
757760
}
758761

759762
return pass
@@ -799,11 +802,11 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
799802
}
800803
l, ok := getLen(object)
801804
if !ok {
802-
return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...)
805+
return Fail(t, fmt.Sprintf("%q could not be applied builtin len()", truncatingFormat("%v", object)), msgAndArgs...)
803806
}
804807

805808
if l != length {
806-
return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
809+
return Fail(t, fmt.Sprintf("%q should have %d item(s), but has %d", truncatingFormat("%v", object), length, l), msgAndArgs...)
807810
}
808811
return true
809812
}
@@ -854,7 +857,7 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{
854857
}
855858

856859
if ObjectsAreEqual(expected, actual) {
857-
return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
860+
return Fail(t, fmt.Sprintf("Should not be: %s\n", truncatingFormat("%#v", actual)), msgAndArgs...)
858861
}
859862

860863
return true
@@ -870,7 +873,7 @@ func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...inte
870873
}
871874

872875
if ObjectsAreEqualValues(expected, actual) {
873-
return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
876+
return Fail(t, fmt.Sprintf("Should not be: %s\n", truncatingFormat("%#v", actual)), msgAndArgs...)
874877
}
875878

876879
return true
@@ -932,10 +935,10 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
932935

933936
ok, found := containsElement(s, contains)
934937
if !ok {
935-
return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
938+
return Fail(t, fmt.Sprintf("%s could not be applied builtin len()", truncatingFormat("%#v", s)), msgAndArgs...)
936939
}
937940
if !found {
938-
return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...)
941+
return Fail(t, fmt.Sprintf("%s does not contain %#v", truncatingFormat("%#v", s), contains), msgAndArgs...)
939942
}
940943

941944
return true
@@ -955,10 +958,10 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
955958

956959
ok, found := containsElement(s, contains)
957960
if !ok {
958-
return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
961+
return Fail(t, fmt.Sprintf("%s could not be applied builtin len()", truncatingFormat("%#v", s)), msgAndArgs...)
959962
}
960963
if found {
961-
return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...)
964+
return Fail(t, fmt.Sprintf("%s should not contain %#v", truncatingFormat("%#v", s), contains), msgAndArgs...)
962965
}
963966

964967
return true
@@ -997,10 +1000,10 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
9971000
av := actualMap.MapIndex(k)
9981001

9991002
if !av.IsValid() {
1000-
return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
1003+
return Fail(t, fmt.Sprintf("%s does not contain %s", truncatingFormat("%#v", list), truncatingFormat("%#v", subset)), msgAndArgs...)
10011004
}
10021005
if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
1003-
return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
1006+
return Fail(t, fmt.Sprintf("%s does not contain %s", truncatingFormat("%#v", list), truncatingFormat("%#v", subset)), msgAndArgs...)
10041007
}
10051008
}
10061009

@@ -1015,7 +1018,7 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
10151018
return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...)
10161019
}
10171020
if !found {
1018-
return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...)
1021+
return Fail(t, fmt.Sprintf("%s does not contain %#v", truncatingFormat("%#v", list), element), msgAndArgs...)
10191022
}
10201023
}
10211024

@@ -1062,7 +1065,7 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
10621065
}
10631066
}
10641067

1065-
return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
1068+
return Fail(t, fmt.Sprintf("%s is a subset of %s", truncatingFormat("%#v", subset), truncatingFormat("%#v", list)), msgAndArgs...)
10661069
}
10671070

10681071
subsetList := reflect.ValueOf(subset)
@@ -1077,7 +1080,7 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
10771080
}
10781081
}
10791082

1080-
return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
1083+
return Fail(t, fmt.Sprintf("%s is a subset of %s", truncatingFormat("%#v", subset), truncatingFormat("%#v", list)), msgAndArgs...)
10811084
}
10821085

10831086
// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
@@ -1581,7 +1584,7 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
15811584
if h, ok := t.(tHelper); ok {
15821585
h.Helper()
15831586
}
1584-
return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
1587+
return Fail(t, fmt.Sprintf("Received unexpected error:\n%s", truncatingFormat("%+v", err)), msgAndArgs...)
15851588
}
15861589

15871590
return true
@@ -1622,7 +1625,7 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte
16221625
if expected != actual {
16231626
return Fail(t, fmt.Sprintf("Error message not equal:\n"+
16241627
"expected: %q\n"+
1625-
"actual : %q", expected, actual), msgAndArgs...)
1628+
"actual : %s", expected, truncatingFormat("%q", actual)), msgAndArgs...)
16261629
}
16271630
return true
16281631
}
@@ -1642,7 +1645,7 @@ func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...in
16421645

16431646
actual := theError.Error()
16441647
if !strings.Contains(actual, contains) {
1645-
return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...)
1648+
return Fail(t, fmt.Sprintf("Error %s does not contain %#v", truncatingFormat("%#v", actual), contains), msgAndArgs...)
16461649
}
16471650

16481651
return true
@@ -1710,7 +1713,7 @@ func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
17101713
h.Helper()
17111714
}
17121715
if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
1713-
return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
1716+
return Fail(t, fmt.Sprintf("Should be zero, but was %s", truncatingFormat("%v", i)), msgAndArgs...)
17141717
}
17151718
return true
17161719
}
@@ -2103,8 +2106,8 @@ func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
21032106
chain := buildErrorChainString(err)
21042107

21052108
return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+
2106-
"expected: %q\n"+
2107-
"in chain: %s", expectedText, chain,
2109+
"expected: %s\n"+
2110+
"in chain: %s", truncatingFormat("%q", expectedText), truncatingFormat("%s", chain),
21082111
), msgAndArgs...)
21092112
}
21102113

@@ -2126,8 +2129,8 @@ func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
21262129
chain := buildErrorChainString(err)
21272130

21282131
return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
2129-
"found: %q\n"+
2130-
"in chain: %s", expectedText, chain,
2132+
"found: %s\n"+
2133+
"in chain: %s", truncatingFormat("%q", expectedText), truncatingFormat("%s", chain),
21312134
), msgAndArgs...)
21322135
}
21332136

@@ -2145,7 +2148,7 @@ func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{
21452148

21462149
return Fail(t, fmt.Sprintf("Should be in error chain:\n"+
21472150
"expected: %q\n"+
2148-
"in chain: %s", target, chain,
2151+
"in chain: %s", target, truncatingFormat("%s", chain),
21492152
), msgAndArgs...)
21502153
}
21512154

@@ -2163,7 +2166,7 @@ func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interfa
21632166

21642167
return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
21652168
"found: %q\n"+
2166-
"in chain: %s", target, chain,
2169+
"in chain: %s", target, truncatingFormat("%s", chain),
21672170
), msgAndArgs...)
21682171
}
21692172

0 commit comments

Comments
 (0)