notice

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 3, 2025 License: MIT Imports: 4 Imported by: 2

README

Notice Package

The notice package provides a set of utilities for building structured assertion messages. It's designed to create easy to read and understand error messages with a header and contextual rows. The package supports fluent interfaces for building messages and includes helper functions for formatting and unwrapping errors.

Usage

Creating a basic message

msg := New("expected %s to be equal", "values").
    Want("%s", "abc").
    Have("%s", "xyz")

fmt.Println(msg.Error())

Output:

expected values to be equal:
  want: abc
  have: xyz

For more examples see examples_test.go file.

Formatting Lines

lines := notice.Lines(1, "line1\nline2\nline3")

fmt.Println(lines)

Output:

  >| line1
  >| line2
  >| line3

Documentation

Overview

Package notice simplifies building structured assertion messages.

Index

Examples

Constants

View Source
const ContinuationHeader = " ---"

ContinuationHeader is a special [Notice.Header] separating notices with the same header.

Example:

header:
  want: want 0
  have: have 0
 ---
  want: want 1
  have: have 1

Variables

View Source
var ErrAssert = errors.New("assert error")

ErrAssert represents an error that occurs during an assertion. It is typically used when a condition fails to meet the expected value.

Functions

func Indent

func Indent(n int, r rune, lns string) string

Indent indents lines with n number of runes. Lines are indented only if there are more than one line.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	lines := notice.Indent(4, ' ', "line1\nline2\nline3")

	fmt.Println(lines)
}
Output:

    line1
    line2
    line3

func Unwrap

func Unwrap(err error) []error

Unwrap unwraps joined errors. Returns nil if err is nil, unwraps only non-nil errors.

Types

type Notice

type Notice struct {
	Header string            // Header message.
	Rows   map[string]string // Context rows.
	Order  []string          // Order to display rows in.
	// contains filtered or unexported fields
}

Notice represents structured notice message consisting of a header and multiple named rows giving context to it.

nolint: errname

func From

func From(err error, prefix ...string) *Notice

From returns instance of Notice if it is in err's tree. If prefix is not empty header will be prefixed with the first element in the slice. If err is not instance of Notice it will create a new one and wrap err.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	var err error
	err = notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz")

	msg := notice.From(err, "optional prefix").
		Append("my", "%s", "value")

	fmt.Println(msg)
}
Output:

[optional prefix] expected values to be equal:
  want: abc
  have: xyz
    my: value

func New

func New(header string, args ...any) *Notice

New creates a new Notice with the specified header which is constructed using fmt.Sprintf from format and args. By default, the base error is set to ErrAssert.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz")

	fmt.Println(msg)
}
Output:

expected values to be equal:
  want: abc
  have: xyz
Example (Formated)
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected %s to be equal", "values").
		Want("%s", "abc").
		Have("%s", "xyz")

	fmt.Println(msg)
}
Output:

expected values to be equal:
  want: abc
  have: xyz

func (*Notice) Append

func (msg *Notice) Append(name, format string, args ...any) *Notice

Append appends a new row with the specified name and value build using fmt.Sprintf from format and args. If a row with the same name already exists, it is moved to the end of the [Notice.Order] slice. Implements fluent interface.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected %s to be equal", "values").
		Want("%s", "abc").
		Have("%s", "xyz").
		Append("name", "%d", 5)

	fmt.Println(msg)
}
Output:

expected values to be equal:
  want: abc
  have: xyz
  name: 5

func (*Notice) AppendRow

func (msg *Notice) AppendRow(desc ...Row) *Notice

AppendRow appends description rows to the message.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	row0 := notice.NewRow("number", "%d", 5)
	row1 := notice.NewRow("string", "%s", "abc")

	msg := notice.New("expected %s to be equal", "values").
		Want("%s", "abc").
		Have("%s", "xyz").
		AppendRow(row0, row1)

	fmt.Println(msg)
}
Output:

expected values to be equal:
    want: abc
    have: xyz
  number: 5
  string: abc

func (*Notice) Error

func (msg *Notice) Error() string

Notice returns a formatted string representation of the Notice.

func (*Notice) Have

func (msg *Notice) Have(format string, args ...any) *Notice

Have uses Append method to append a row with "have" name. If the "have" row already exists it will just replace its value.

func (*Notice) Is

func (msg *Notice) Is(target error) bool

func (*Notice) Prepend

func (msg *Notice) Prepend(name, format string, args ...any) *Notice

Prepend prepends a new row with the specified name and value built using fmt.Sprintf from format and args. If a row with the same name already exists, it is moved to the beginning of the [Notice.Order] slice. Implements fluent interface.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected %s to be equal", "values").
		Trail("type.field").
		Want("%s", "abc").
		Have("%s", "xyz").
		Prepend("name", "%d", 5)

	fmt.Println(msg)
}
Output:

expected values to be equal:
  trail: type.field
   name: 5
   want: abc
   have: xyz

func (*Notice) Remove

func (msg *Notice) Remove(name string) *Notice

Remove removes named row.

func (*Notice) SetHeader

func (msg *Notice) SetHeader(header string, args ...any) *Notice

SetHeader sets the header message. Implements fluent interface.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected %s to be equal", "values").
		Want("%s", "abc").
		Have("%s", "xyz")

	_ = msg.SetHeader("some other %s", "header")

	fmt.Println(msg)
}
Output:

some other header:
  want: abc
  have: xyz

func (*Notice) Trail

func (msg *Notice) Trail(tr string) *Notice

Trail adds trail row if "tr" is not empty string. If the trail row already exists it overwrites it. Implements fluent interface.

Trail examples:

  • Type
  • Type[1].Field
  • Type["key"].Field
Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected %s to be equal", "values").
		Trail("type.field").
		Want("%s", "abc").
		Have("%s", "xyz")

	fmt.Println(msg)
}
Output:

expected values to be equal:
  trail: type.field
   want: abc
   have: xyz

func (*Notice) Want

func (msg *Notice) Want(format string, args ...any) *Notice

Want uses Append method to append a row with "want" name. If the "want" row already exists it will just replace its value.

func (*Notice) Wrap

func (msg *Notice) Wrap(err error) *Notice

Wrap wraps base error with provided one.

type Row

type Row struct {
	Name   string
	Format string
	Args   []any
}

Row represents Notice row.

func NewRow

func NewRow(name, format string, args ...any) Row

NewRow is constructor function for Row.

func Trail

func Trail(name string) Row

Trail is convenience constructor function for Row with given name.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL