The format package provides pretty-printing and formatting utilities for Gomega's output. It recursively explores objects to generate formatted, indented representations with type information, making test failures easier to understand.
go get github.com/onsi/gomegaimport "github.com/onsi/gomega/format"The format package controls how Gomega displays values in assertion failure messages. It provides:
These package-level variables control formatting behavior:
// Maximum recursion depth when printing nested structures (default: 10)
var MaxDepth uint = 10
// Maximum string length before truncation (default: 4000)
// Set to 0 to disable truncation
var MaxLength int = 4000
// Use GoString() or String() methods instead of recursive inspection (default: false)
var UseStringerRepresentation bool = false
// Print internal details of context.Context objects (default: false)
var PrintContextObjects bool = false
// Display truncated diffs for long strings (default: true)
var TruncatedDiff bool = true
// Minimum string length before truncation in diffs (default: 50)
var TruncateThreshold uint = 50
// Characters of context around diff mismatches (default: 5)
var CharactersAroundMismatchToInclude uint = 5
// Default indentation string (default: " " - 4 spaces)
var Indent string = " "import "github.com/onsi/gomega/format"
// Increase recursion depth for deeply nested structures
format.MaxDepth = 20
// Show more context in string diffs
format.CharactersAroundMismatchToInclude = 10
// Use String()/GoString() methods when available
format.UseStringerRepresentation = true
// Disable truncation for very long output
format.MaxLength = 0
// Use 2-space indentation
format.Indent = " "func Object(object any, indentation uint) stringPretty-prints an object with the specified indentation level. Recursively explores nested structures and generates formatted output with type information.
Parameters:
object any: The object to formatindentation uint: Indentation level (multiplied by Indent string)Returns:
string: Formatted representation of the objectExample:
type User struct {
Name string
Age int
Tags []string
}
user := User{
Name: "Alice",
Age: 30,
Tags: []string{"admin", "developer"},
}
output := format.Object(user, 1)
// Output:
// <format_test.User>: {Name: "Alice", Age: 30, Tags: ["admin", "developer"]}func Message(actual any, message string, expected ...any) stringGenerates a formatted matcher failure message showing actual and expected values.
Parameters:
actual any: The actual value that was testedmessage string: The comparison message (e.g., "to equal", "not to equal")expected ...any: Optional expected value (if omitted, only actual is shown)Returns:
string: Formatted failure messageExample:
actual := 42
expected := 50
msg := format.Message(actual, "to equal", expected)
// Output:
// Expected
// <int>: 42
// to equal
// <int>: 50func MessageWithDiff(actual, message, expected string) stringFormats a failure message with diff highlighting for strings. When strings exceed TruncateThreshold, it truncates them and shows a visual indicator pointing to the first difference.
Parameters:
actual string: The actual string valuemessage string: The comparison messageexpected string: The expected string valueReturns:
string: Formatted message with diff indicatorExample:
actual := "The quick brown fox jumps over the lazy dog"
expected := "The quick brown cat jumps over the lazy dog"
msg := format.MessageWithDiff(actual, "to equal", expected)
// Output shows truncated strings with | indicator pointing to "fox" vs "cat" differencefunc IndentString(s string, indentation uint) stringIndents each line of a multi-line string by the specified indentation level.
Parameters:
s string: The string to indentindentation uint: Indentation level (multiplied by Indent string)Returns:
string: Indented stringExample:
text := "Line 1\nLine 2\nLine 3"
indented := format.IndentString(text, 2)
// Output:
// Line 1
// Line 2
// Line 3func RegisterCustomFormatter(customFormatter CustomFormatter) CustomFormatterKeyRegisters a custom formatter function that can handle formatting specific types. Custom formatters are checked before default formatting logic.
Parameters:
customFormatter CustomFormatter: Function that formats valuesReturns:
CustomFormatterKey: Key for unregistering the formatter laterExample:
import (
"fmt"
"time"
"github.com/onsi/gomega/format"
)
// Register custom formatter for time.Duration
key := format.RegisterCustomFormatter(func(value any) (string, bool) {
if duration, ok := value.(time.Duration); ok {
return fmt.Sprintf("Duration: %s", duration), true
}
return "", false
})
// Later, unregister if needed
defer format.UnregisterCustomFormatter(key)func UnregisterCustomFormatter(key CustomFormatterKey)Unregisters a previously registered custom formatter.
Parameters:
key CustomFormatterKey: The key returned by RegisterCustomFormatterExample:
key := format.RegisterCustomFormatter(myFormatter)
// ... use the formatter ...
format.UnregisterCustomFormatter(key)type GomegaStringer interface {
GomegaString() string
}Interface for types that provide custom Gomega-specific string representations. When an object implements this interface, GomegaString() is always called for formatting, regardless of the UseStringerRepresentation setting.
Notes:
fmt.GoStringer and fmt.StringerMaxLengthExample:
type DatabaseConnection struct {
Host string
Port int
Password string // Sensitive data
}
func (db DatabaseConnection) GomegaString() string {
// Provide safe representation without password
return fmt.Sprintf("DatabaseConnection{Host: %s, Port: %d, Password: <redacted>}",
db.Host, db.Port)
}
// Now when used in assertions, password is hidden
conn := DatabaseConnection{Host: "localhost", Port: 5432, Password: "secret123"}
// format.Object(conn, 1) will use GomegaString() automaticallytype CustomFormatter func(value any) (string, bool)Function type for custom formatters. The formatter inspects the value and either handles it by returning (formatted-string, true) or declines by returning ("", false).
Parameters:
value any: The value to potentially formatReturns:
string: The formatted representation (if handled)bool: True if the formatter handled this value, false otherwiseNotes:
GomegaStringer, fmt.GoStringer, and fmt.StringerExample:
import (
"encoding/json"
"github.com/onsi/gomega/format"
)
// Custom formatter for JSON-serializable types
jsonFormatter := func(value any) (string, bool) {
// Only handle slices and maps
v := reflect.ValueOf(value)
if v.Kind() != reflect.Slice && v.Kind() != reflect.Map {
return "", false
}
jsonBytes, err := json.MarshalIndent(value, "", " ")
if err != nil {
return "", false
}
return string(jsonBytes), true
}
key := format.RegisterCustomFormatter(jsonFormatter)
defer format.UnregisterCustomFormatter(key)
// Now maps and slices will be formatted as JSON in test output
data := map[string]int{"foo": 1, "bar": 2}
fmt.Println(format.Object(data, 1))type CustomFormatterKey intOpaque key type returned by RegisterCustomFormatter and used with UnregisterCustomFormatter. The actual value should not be relied upon or manipulated.
import (
"fmt"
"github.com/onsi/gomega/format"
)
type Person struct {
Name string
Age int
Address Address
}
type Address struct {
Street string
City string
}
person := Person{
Name: "Bob",
Age: 25,
Address: Address{
Street: "123 Main St",
City: "Springfield",
},
}
output := format.Object(person, 1)
fmt.Println(output)
// Output:
// <main.Person>: {
// Name: "Bob",
// Age: 25,
// Address: {Street: "123 Main St", City: "Springfield"},
// }import "github.com/onsi/gomega/format"
type Credentials struct {
Username string
APIKey string
}
// Register formatter to redact sensitive data
key := format.RegisterCustomFormatter(func(value any) (string, bool) {
if creds, ok := value.(Credentials); ok {
return fmt.Sprintf("Credentials{Username: %q, APIKey: <redacted>}",
creds.Username), true
}
return "", false
})
defer format.UnregisterCustomFormatter(key)
creds := Credentials{Username: "admin", APIKey: "secret-key-123"}
fmt.Println(format.Object(creds, 1))
// Output: <main.Credentials>: Credentials{Username: "admin", APIKey: <redacted>}import (
"fmt"
"github.com/onsi/gomega/format"
)
type ComplexObject struct {
data []byte
}
func (co ComplexObject) GomegaString() string {
return fmt.Sprintf("ComplexObject with %d bytes", len(co.data))
}
obj := ComplexObject{data: make([]byte, 1024)}
fmt.Println(format.Object(obj, 1))
// Output: <main.ComplexObject>: ComplexObject with 1024 bytesimport (
"github.com/onsi/gomega"
"github.com/onsi/gomega/format"
)
// Configure format package before running tests
func init() {
// Show more context in diffs
format.CharactersAroundMismatchToInclude = 10
// Increase max depth for nested structures
format.MaxDepth = 15
// Use 2-space indentation
format.Indent = " "
// Don't truncate output
format.MaxLength = 0
}
func TestWithCustomFormatting(t *testing.T) {
gomega.RegisterTestingT(t)
actual := buildComplexObject()
expected := buildExpectedObject()
// Assertions will use custom formatting
gomega.Expect(actual).To(gomega.Equal(expected))
}import "github.com/onsi/gomega/format"
actual := "The quick brown fox jumps over the lazy dog"
expected := "The quick brown cat jumps over the lazy dog"
msg := format.MessageWithDiff(actual, "to equal", expected)
fmt.Println(msg)
// Output shows:
// Expected
// <string>: "...brown fox ju..."
// to equal |
// <string>: "...brown cat ju..."
// The | indicator points to the first differenceThe format package is used automatically by Gomega matchers to generate failure messages. You typically don't need to call format functions directly unless you're creating custom matchers.
import (
. "github.com/onsi/gomega"
"github.com/onsi/gomega/format"
"github.com/onsi/gomega/types"
)
// Custom matcher that uses format package
type customMatcher struct {
expected string
}
func (m *customMatcher) Match(actual any) (success bool, err error) {
actualStr, ok := actual.(string)
if !ok {
return false, fmt.Errorf("expected string, got %T", actual)
}
return actualStr == m.expected, nil
}
func (m *customMatcher) FailureMessage(actual any) string {
// Use format.Message to generate consistent output
return format.Message(actual, "to equal", m.expected)
}
func (m *customMatcher) NegatedFailureMessage(actual any) string {
return format.Message(actual, "not to equal", m.expected)
}