Testify Failure Messages and Diff Output Made Readable
Read testify's Equal failure output: the expected and actual lines, the unified diff of a nested struct and map, a long string, and how to shorten it.

The first time you see a testify failure for a large struct, it is a wall of text. The second time, you know where to look. This short note walks through the format on Go 1.25.6, testify v1.11.1, and gives a way to read it quickly.
Tested with Go 1.25.6, testify v1.11.1, macOS on Apple Silicon (arm64)
package main
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
type Order struct {
ID string
Lines []Line
Meta map[string]string
}
type Line struct {
SKU string
Qty int
}
func TestStructDiff(t *testing.T) {
want := Order{"o-1", []Line{{"pen", 2}, {"book", 1}}, map[string]string{"channel": "web"}}
got := Order{"o-1", []Line{{"pen", 2}, {"book", 3}}, map[string]string{"channel": "app"}}
assert.Equal(t, want, got)
}
func TestLongStringDiff(t *testing.T) {
want := strings.Repeat("alpha\n", 4) + "beta\n" + strings.Repeat("gamma\n", 4)
got := strings.Repeat("alpha\n", 4) + "BETA\n" + strings.Repeat("gamma\n", 4)
assert.Equal(t, want, got)
}
func main() {}go test -count=1 -v . 2>&1 | grep -vE '^(=== RUN|=== PAUSE|=== CONT|=== NAME|PASS|ok|FAIL$|FAIL\s|exit status)' | sed -E 's/ \([0-9.]+s\)//; s#^ +[a-z_0-9]+\.go:[0-9]+: # #; s/\x1b\[[0-9;]*m//g; s#/[^[:space:]]*/([a-z_0-9]+\.go)#\1#g; s/[[:space:]]+$//' | grep -vE '^\s*$' Error Trace: diff_test.go:23
Error: Not equal:
expected: main.Order{ID:"o-1", Lines:[]main.Line{main.Line{SKU:"pen", Qty:2}, main.Line{SKU:"book", Qty:1}}, Meta:map[string]string{"channel":"web"}}
actual : main.Order{ID:"o-1", Lines:[]main.Line{main.Line{SKU:"pen", Qty:2}, main.Line{SKU:"book", Qty:3}}, Meta:map[string]string{"channel":"app"}}
Diff:
--- Expected
+++ Actual
@@ -9,3 +9,3 @@
SKU: (string) (len=4) "book",
- Qty: (int) 1
+ Qty: (int) 3
}
@@ -13,3 +13,3 @@
Meta: (map[string]string) (len=1) {
- (string) (len=7) "channel": (string) (len=3) "web"
+ (string) (len=7) "channel": (string) (len=3) "app"
}
Test: TestStructDiff
--- FAIL: TestStructDiff
Error Trace: diff_test.go:29
Error: Not equal:
expected: "alpha\nalpha\nalpha\nalpha\nbeta\ngamma\ngamma\ngamma\ngamma\n"
actual : "alpha\nalpha\nalpha\nalpha\nBETA\ngamma\ngamma\ngamma\ngamma\n"
Diff:
--- Expected
+++ Actual
@@ -4,3 +4,3 @@
alpha
-beta
+BETA
gamma
Test: TestLongStringDiff
--- FAIL: TestLongStringDiffReading a struct diff
The failure has four parts: the Error Trace line (the assertion's file and line), Error: Not equal:, then expected: and actual : on single lines, then Diff:. The single-line forms are Go syntax from %#v, which is long for nested values, and reading them for a difference is slow. Go to the diff instead.
The diff is in unified format, produced from a pretty-printed dump of both values. The header says --- Expected and +++ Actual. A hunk starts with @@ -9,3 +9,3 @@, meaning three lines starting at line 9 of the expected dump against three at line 9 of the actual. Lines that begin with - exist only in the expected value, lines with + only in the actual one, and lines with a leading space are unchanged context.
In the struct test there are two hunks. The first shows - Qty: (int) 1 and + Qty: (int) 3 under the line SKU: (string) (len=4) "book", so the second line item's quantity differs. The second hunk shows the map entry "channel": "web" against "app". Reading the context lines above each change tells you which element of the slice and which key of the map: the dump has the indentation and the field names.
Strings
For multi-line strings, the diff compares line by line. The long string test has four alpha lines, one beta against BETA and four gamma lines. The hunk @@ -4,3 +4,3 @@ shows alpha, -beta, +BETA, gamma: one line of context on each side and the change. It is the same view as git diff, and it turns a nine-line mismatch into a four-line report. The expected: and actual : lines above are the escaped strings, with the newline characters shown as escapes, which is useful when the difference is whitespace.
Types in the dump
The pretty-printed form prints each value with its type and, for strings, its length: (string) (len=4) "book", (int) 1. Those annotations are not decoration. A failure where the visible text looks identical often comes down to a type or length difference: an int against an int64, a string with a trailing space (the lengths differ by one), a []byte against a string. If the diff shows a changed line that reads the same to you, compare the type and length in parentheses before looking elsewhere.
Making it shorter
- Compare a projection. If one field matters, assert on it:
assert.Equal(t, want.Qty, got.Lines[1].Qty). The failure is two numbers. - Use
ElementsMatchfor unordered slices, which reports the elements missing and extra, not a positional diff. - Use
JSONEqfor JSON. It reports the two documents formatted. - Print the diff, not the dump.
go-cmpprints only the differing parts; see the libraries compared. - Shrink the data. Tests with small, purposeful fixtures produce small failures.
The format is produced by testify's assert package; see the assertions tutorial and the package documentation.


