or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-assertions.mdformat.mdgbytes.mdgcustom.mdgexec.mdghttp.mdgleak.mdgmeasure.mdgstruct.mdindex.mdmatchers.mdtypes-interfaces.md
tile.json

format.mddocs/

Format Package

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.

Package Information

  • Package Name: github.com/onsi/gomega/format
  • Package Type: golang
  • Language: Go
  • Installation: go get github.com/onsi/gomega

Import

import "github.com/onsi/gomega/format"

Overview

The format package controls how Gomega displays values in assertion failure messages. It provides:

  • Recursive pretty-printing with configurable depth limits
  • Customizable output formatting via configuration variables
  • Support for custom formatters and GomegaStringer interface
  • Intelligent string diff generation for improved readability
  • Truncation handling for large objects

Configuration Variables

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 = "    "

Configuration Examples

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 = "  "

Functions

Object

func Object(object any, indentation uint) string

Pretty-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 format
  • indentation uint: Indentation level (multiplied by Indent string)

Returns:

  • string: Formatted representation of the object

Example:

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"]}

Message

func Message(actual any, message string, expected ...any) string

Generates a formatted matcher failure message showing actual and expected values.

Parameters:

  • actual any: The actual value that was tested
  • message 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 message

Example:

actual := 42
expected := 50
msg := format.Message(actual, "to equal", expected)
// Output:
// Expected
//     <int>: 42
// to equal
//     <int>: 50

MessageWithDiff

func MessageWithDiff(actual, message, expected string) string

Formats 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 value
  • message string: The comparison message
  • expected string: The expected string value

Returns:

  • string: Formatted message with diff indicator

Example:

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" difference

IndentString

func IndentString(s string, indentation uint) string

Indents each line of a multi-line string by the specified indentation level.

Parameters:

  • s string: The string to indent
  • indentation uint: Indentation level (multiplied by Indent string)

Returns:

  • string: Indented string

Example:

text := "Line 1\nLine 2\nLine 3"
indented := format.IndentString(text, 2)
// Output:
//         Line 1
//         Line 2
//         Line 3

RegisterCustomFormatter

func RegisterCustomFormatter(customFormatter CustomFormatter) CustomFormatterKey

Registers a custom formatter function that can handle formatting specific types. Custom formatters are checked before default formatting logic.

Parameters:

  • customFormatter CustomFormatter: Function that formats values

Returns:

  • CustomFormatterKey: Key for unregistering the formatter later

Example:

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)

UnregisterCustomFormatter

func UnregisterCustomFormatter(key CustomFormatterKey)

Unregisters a previously registered custom formatter.

Parameters:

  • key CustomFormatterKey: The key returned by RegisterCustomFormatter

Example:

key := format.RegisterCustomFormatter(myFormatter)
// ... use the formatter ...
format.UnregisterCustomFormatter(key)

Types

GomegaStringer

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:

  • Takes precedence over fmt.GoStringer and fmt.Stringer
  • Output is not truncated by MaxLength
  • Useful for providing test-friendly representations

Example:

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() automatically

CustomFormatter

type 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 format

Returns:

  • string: The formatted representation (if handled)
  • bool: True if the formatter handled this value, false otherwise

Notes:

  • Strings returned by custom formatters are not truncated
  • Multiple formatters can be registered; they're checked in registration order
  • Custom formatters are evaluated before GomegaStringer, fmt.GoStringer, and fmt.Stringer

Example:

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))

CustomFormatterKey

type CustomFormatterKey int

Opaque key type returned by RegisterCustomFormatter and used with UnregisterCustomFormatter. The actual value should not be relied upon or manipulated.

Usage Examples

Basic Object Formatting

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"},
//     }

Custom Formatter for Sensitive Data

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>}

Using GomegaStringer Interface

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 bytes

Configuring Format Output

import (
    "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))
}

String Diff with Highlighting

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 difference

Integration with Gomega Matchers

The 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)
}

Best Practices

When to Use Custom Formatters

  1. Redacting Sensitive Data: Hide passwords, API keys, or PII in test output
  2. Simplifying Complex Types: Provide concise representations of large objects
  3. Domain-Specific Formatting: Show objects in a format meaningful to your domain
  4. Performance: Avoid expensive reflection when you know the type

When to Use GomegaStringer

  1. Type-Specific Control: When you control the type definition
  2. Always Active: When you want the format used regardless of settings
  3. Test-Specific Output: When standard String() is for production, GomegaString() is for tests

Configuration Tips

  1. MaxDepth: Increase for deeply nested structures, decrease to prevent excessive output
  2. MaxLength: Set to 0 when debugging to see full output, keep default for regular test runs
  3. TruncateThreshold: Lower values show more context in diffs but create longer messages
  4. UseStringerRepresentation: Enable when String() methods provide better readability than reflection

Performance Considerations

  • Custom formatters are fastest (no reflection overhead)
  • GomegaStringer is second fastest
  • Default reflection-based formatting is slowest
  • For frequently formatted types in performance-critical tests, consider custom formatters

Related Packages

  • Main Package - Core Gomega assertions
  • Types Package - Core interfaces including GomegaMatcher
  • GCustom Package - Custom matcher creation utilities