assert

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Apr 18, 2025 License: MIT Imports: 6 Imported by: 0

README

The assert package

The assert package is a toolkit for Go testing that offers common assertions, integrating well with the standard library. When writing tests, developers often face a choice between using Go's standard testing package or packages like assert. The standard library requires verbose if statements for assertions, which can make tests harder to read. This package, on the other hand, provides one-line asserts, such as assert.NoError, which are more concise and clear. This simplicity helps quickly grasp the intent of each test, enhancing readability.

By making tests easier to write and read, this package hopes to encourage developers to invest more time in testing. Features like immediate feedback with easily readable output and a wide range of assertion functions lower the barrier to writing comprehensive tests. This can lead to better code coverage, as developers are more likely to write and maintain tests when the process is straightforward and rewarding.

Assertions

Most of the assertions are self-explanatory and I encourage you to see your online documentation. Here we will highlight only the ones that we feel are interesting.

Asserting Structures
type T struct {
    Int int
    Str string
}

have := T{Int: 1, Str: "abc"}
want := T{Int: 2, Str: "xyz"}

assert.Equal(want, have)
// Test Log:
//
// expected values to be equal:
//   trail: T.Int
//    want: 2
//    have: 1
//  ---
//   trail: T.Str
//    want: "xyz"
//    have: "abc"
Asserting Recursive Structures
type T struct {
    Int  int
    Next *T
}

have := T{1, &T{2, &T{3, &T{42, nil}}}}
want := T{1, &T{2, &T{3, &T{4, nil}}}}

assert.Equal(want, have)

// Test Log:
//
// expected values to be equal:
//   trail: T.Next.Next.Next.Int
//    want: 4
//    have: 42
Asserting Maps, Arrays and Slices

Maps

type T struct {
    Str string
}

want := map[int]T{1: {Str: "abc"}, 2: {Str: "xyz"}}
have := map[int]T{1: {Str: "abc"}, 3: {Str: "xyz"}}

assert.Equal(want, have)

// Test Log:
//
// expected values to be equal:
//       trail: map[2]
//        want:
//              map[int]T{
//                1: {
//                  Str: "abc",
//                },
//                3: {
//                  Str: "xyz",
//                },
//              }
//        have: nil
//   want type: map[int]T
//   have type: <nil>

Slices and arrays

want := []int{1, 2, 3}
have := []int{1, 2, 3, 4}

assert.Equal(want, have)

// Test Log:
//
// expected values to be equal:
//   want len: 3
//   have len: 4
//       want:
//             []int{
//               1,
//               2,
//               3,
//             }
//       have:
//             []int{
//               1,
//               2,
//               3,
//               4,
//             }
Asserting Time
want := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
have := time.Date(2025, 1, 1, 0, 1, 1, 0, time.UTC)

assert.Time(want, have)

// Test Log:
//
//  expected equal dates:
//   want: 2025-01-01T00:00:00Z
//   have: 2025-01-01T00:01:01Z
//   diff: -1m1s
Asserting JSON Strings
want := `{"A": 1, "B": 2}`
have := `{"A": 1, "B": 3}`

assert.JSON(want, have)

// Test Log:
//
// expected JSON strings to be equal:
//   want: {"A":1,"B":2}
//   have: {"A":1,"B":3}
Worthy mentions
  • Epsilon - assert floating point numbers within given ε.
  • ChannelWillClose - assert channel will be closed within given time.
  • MapSubset - checks the "want" is a subset "have".

See the documentation for the full list.

Advanced usage

Custom Checkers

You can define custom checkers for any trail define a function matching check.Check. See example below.

type T struct {
    Str string
    Any []any
}

chk := func(want, have any, opts ...check.Option) error {
    wVal := want.(float64)
    hVal := want.(float64)
    return check.Epsilon(wVal, 0.01, hVal, opts...)
}
opt := check.WithTrailChecker("T.Any[1]", chk)

want := T{Str: "abc", Any: []any{1, 2.123, "abc"}}
have := T{Str: "abc", Any: []any{1, 2.124, "abc"}}

assert.Equal(want, have, opt)

// Test Log:
//
//  <nil>

The trail uniquely identifies the struct field, slice or array element, or map key the assertion visits. The assert package tracks the tails for all composite types. To see all visited trails do this:

type T struct {
    Int  int
    Next *T
}

have := T{1, &T{2, &T{3, &T{42, nil}}}}
want := T{1, &T{2, &T{3, &T{42, nil}}}}
trails := make([]string, 0)

assert.Equal(want, have, check.WithTrailLog(&trails))

fmt.Println(strings.Join(trails, "\n"))
// Output:
// T.Int
// T.Next.Int
// T.Next.Next.Int
// T.Next.Next.Next.Int
// T.Next.Next.Next.Next
Skipping Fields, Elements, or Indexes

You can ask certain trials to be skipped when asserting.

type T struct {
    Int  int
    Next *T
}

have := T{1, &T{2, &T{3, &T{42, nil}}}}
want := T{1, &T{2, &T{8, &T{42, nil}}}}
trails := make([]string, 0)

assert.Equal(
    want,
    have,
    check.WithTrailLog(&trails),
    check.WithSkipTrail("T.Next.Next.Int"),
)

fmt.Println(strings.Join(trails, "\n"))
// Test Log:
//
// T.Int
// T.Next.Int
// T.Next.Next.Int <skipped>
// T.Next.Next.Next.Int
// T.Next.Next.Next.Next

Notice that the requested trail was skipped from assertion even though the values were not equal 3 != 8. The skipped paths are always marked with <skipped> tag.

Skipping unexported fields

The assert.Equal will fail the test if the compared values (structs) have unexported fields. This happens by design to make sure the equality check doesn't silently ignore unexported fields. In cases like this the testing module requires from a developer either explicitly specify fields to skip during comparison or enable a mode that ignores all unexported fields, as supported by the testing framework.

type T struct {
    Int  int
    prv  int
    Next *T
}

have := T{1, -1, &T{2, -2, &T{3, -3, &T{42, -4, nil}}}}
want := T{1, -7, &T{2, -7, &T{3, -7, &T{42, -7, nil}}}}
trails := make([]string, 0)

err := check.Equal(
    want,
    have,
    check.WithTrailLog(&trails),
    check.WithSkipUnexported,
)

fmt.Println(err)
fmt.Println(strings.Join(trails, "\n"))
// Output:
// <nil>
// T.Int
// T.prv <skipped>
// T.Next.Int
// T.Next.prv <skipped>
// T.Next.Next.Int
// T.Next.Next.prv <skipped>
// T.Next.Next.Next.Int
// T.Next.Next.Next.prv <skipped>
// T.Next.Next.Next.Next

Documentation

Overview

Package assert provides assertion functions.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func After

func After(t tester.T, date, mark time.Time, opts ...check.Option) bool

After asserts "date" is after "mark". Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

The "date" and "mark" might be date representations in form of string, int, int64 or time.Time. For string representations the check.Options.TimeFormat is used during parsing and the returned date is always in UTC. The int and int64 types are interpreted as Unix Timestamp and the date returned is also in UTC.

func AfterOrEqual

func AfterOrEqual(t tester.T, date, mark any, opts ...check.Option) bool

AfterOrEqual asserts "date" is equal or after "mark". Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

The "date" and "mark" might be date representations in form of string, int, int64 or time.Time. For string representations the check.Options.TimeFormat is used during parsing and the returned date is always in UTC. The int and int64 types are interpreted as Unix Timestamp and the date returned is also in UTC.

func Before

func Before(t tester.T, date, mark any, opts ...check.Option) bool

Before asserts "date" is before "mark". Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

The "date" and "mark" might be date representations in form of string, int, int64 or time.Time. For string representations the check.Options.TimeFormat is used during parsing and the returned date is always in UTC. The int and int64 types are interpreted as Unix Timestamp and the date returned is also in UTC.

func BeforeOrEqual

func BeforeOrEqual(t tester.T, date, mark time.Time, opts ...check.Option) bool

BeforeOrEqual asserts "date" is equal or before "mark". Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

The "date" and "mark" might be date representations in form of string, int, int64 or time.Time. For string representations the check.Options.TimeFormat is used during parsing and the returned date is always in UTC. The int and int64 types are interpreted as Unix Timestamp and the date returned is also in UTC.

func ChannelWillClose

func ChannelWillClose[C any](t tester.T, within any, c <-chan C, opts ...check.Option) bool

ChannelWillClose asserts channel will be closed "within" given time duration. Returns true if it was, otherwise marks the test as failed, writes error message to test log and returns false.

The "within" may represent duration in form of a string, int, int64 or time.Duration.

func Contain

func Contain(t tester.T, want, have string, opts ...check.Option) bool

Contain asserts "want" is a substring of "have". Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

func Count

func Count(t tester.T, count int, what, where any, opts ...check.Option) bool

Count asserts there is "count" occurrences of "what" in "where". Returns true if the count matches, otherwise marks the test as failed, writes error message to test log and returns false.

Currently only strings are supported.

func DirExist

func DirExist(t tester.T, pth string, opts ...check.Option) bool

DirExist asserts "pth" points to an existing directory. It fails if the path points to a filesystem entry which is not a directory or there is an error when trying to check the path. Returns true on success, otherwise marks the test as failed, writes error message to test log and returns false.

func Duration

func Duration(t tester.T, want, have any, opts ...check.Option) bool

Duration asserts "want" and "have" durations are equal. Returns true if they are, otherwise marks the test as failed, writes error message to test log and returns false.

The "want" and "have" might be duration representation in form of string, int, int64 or time.Duration.

func Empty

func Empty(t tester.T, have any, opts ...check.Option) bool

Empty asserts "have" is empty. Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

See check.Empty for list of values which are considered empty.

func Epsilon

func Epsilon[T constraints.Number](
	t tester.T,
	want, delta, have T,
	opts ...check.Option,
) bool

Epsilon asserts the difference between two numbers is within a given delta. Returns true if it is, otherwise marks the test as failed, writes error message to test log and returns false.

func Equal

func Equal(t tester.T, want, have any, opts ...check.Option) bool

Equal asserts both values are equal. Returns true if they are, otherwise marks the test as failed, writes error message to test log and returns false.

func Error

func Error(t tester.T, err error, opts ...check.Option) bool

Error asserts "err" is not nil. Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

func ErrorAs

func ErrorAs(t tester.T, err error, target any, opts ...check.Option) bool

ErrorAs finds the first error in "err" tree that matches target, and if one is found, sets target to that error. Returns true if it does, otherwise marks the test as failed, writes error message to test log and returns false.

func ErrorContain

func ErrorContain(t tester.T, want string, err error, opts ...check.Option) bool

ErrorContain asserts "err" is not nil and its message contains "want". Returns true if it does, otherwise marks the test as failed, writes error message to test log and returns false.

func ErrorEqual

func ErrorEqual(t tester.T, want string, err error, opts ...check.Option) bool

ErrorEqual asserts "err" is not nil and its message equals to "want". Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

func ErrorIs

func ErrorIs(t tester.T, err, target error, opts ...check.Option) bool

ErrorIs asserts whether any error in "err" tree matches target. Returns true if it does, otherwise marks the test as failed, writes error message to test log and returns false.

func ErrorRegexp

func ErrorRegexp(t tester.T, want string, err error, opts ...check.Option) bool

ErrorRegexp asserts "err" is not nil and its message matches the "want" regex. Returns true if it does, otherwise marks the test as failed, writes error message to test log and returns false.

The "want" can be either regular expression string or instance of regexp.Regexp. The fmt.Sprint is used to get string representation of have argument.

func Exact

func Exact(t tester.T, want, have any, opts ...check.Option) bool

Exact asserts "want" and "have" dates are equal and are in the same timezone. Returns true if they are, otherwise marks the test as failed, writes error message to test log and returns false.

The "want" and "have" might be date representations in form of string, int, int64 or time.Time. For string representations the [Options.TimeFormat] is used during parsing and the returned date is always in UTC. The int and int64 types are interpreted as Unix Timestamp and the date returned is also in UTC.

func ExitCode

func ExitCode(t tester.T, want int, err error, opts ...check.Option) bool

ExitCode asserts "err" is pointer to [exec.ExitError] with exit code equal to "want". Returns true if it is, otherwise marks the test as failed, writes error message to test log and returns false.

func False

func False(t tester.T, have bool, opts ...check.Option) bool

False asserts "have" is false. Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

func Fields

func Fields(t tester.T, want int, s any, opts ...check.Option) bool

Fields asserts struct or pointer to a struct "s" has "want" number of fields. Returns true if it does, otherwise marks the test as failed, writes error message to test log and returns false.

func FileContain

func FileContain[T check.Content](t tester.T, want T, pth string, opts ...check.Option) bool

FileContain asserts file at "pth" can be read and its string content contains "want". It fails if the path points to a filesystem entry which is not a file or there is an error reading the file. The file is read in full then Contain assertion is used to check it contains "want" string. Returns true on success, otherwise marks the test as failed, writes error message to test log and returns false.

func FileExist

func FileExist(t tester.T, pth string, opts ...check.Option) bool

FileExist asserts "pth" points to an existing file. It fails if the path points to a filesystem entry which is not a file or there is an error when trying to check the path. Returns true on success, otherwise marks the test as failed, writes error message to test log and returns false.

func Has

func Has[T comparable](t tester.T, want T, bag []T, opts ...check.Option) bool

Has asserts slice has "want" value. Returns true if it does, otherwise marks the test as failed, writes error message to test log and returns false.

func HasKey

func HasKey[K comparable, V any](t tester.T, key K, set map[K]V, opts ...check.Option) (V, bool)

HasKey asserts map has a key. Returns true if it does, otherwise marks the test as failed, writes error message to test log and returns false.

func HasKeyValue

func HasKeyValue[K, V comparable](
	t tester.T,
	key K,
	want V,
	set map[K]V,
	opts ...check.Option,
) bool

HasKeyValue asserts map has a key with given value. Returns true if it doesn't, otherwise marks the test as failed, writes error message to test log and returns false.

func HasNo

func HasNo[T comparable](t tester.T, want T, bag []T, opts ...check.Option) bool

HasNo asserts slice does not have "want" value. Returns true if it does not, otherwise marks the test as failed, writes error message to test log and returns false.

func HasNoKey

func HasNoKey[K comparable, V any](t tester.T, key K, set map[K]V, opts ...check.Option) bool

HasNoKey asserts map has no key. Returns true if it doesn't, otherwise marks the test as failed, writes error message to test log and returns false.

func JSON

func JSON(t tester.T, want, have string, opts ...check.Option) bool

JSON asserts that two JSON strings are equivalent. Returns true if they are, otherwise marks the test as failed, writes error message to test log and returns false.

assert.JSON(t, `{"hello": "world"}`, `{"foo": "bar"}`)

func Len

func Len(t tester.T, want int, have any, opts ...check.Option) bool

Len asserts "have" has "want" elements. Returns true if it is, otherwise it marks the test as failed, writes error message to test log and returns false.

func MapSubset

func MapSubset[K cmp.Ordered, V any](
	t tester.T,
	want, have map[K]V,
	opts ...check.Option,
) bool

MapSubset asserts the "want" is a subset "have". In other words all keys and their corresponding values in "want" map must be in "have" map. It is not an error when "have" map has some other keys. Returns true if "want is a subset of "have", otherwise marks the test as failed, writes error message to test log and returns false.

func MapsSubset

func MapsSubset[K cmp.Ordered, V any](
	t tester.T,
	want, have []map[K]V,
	opts ...check.Option,
) bool

MapsSubset asserts all the "want" maps are subsets of corresponding "have" maps using MapSubset. Returns true if all "want" maps are subset of corresponding "have" maps, otherwise marks the test as failed, writes error message to test log and returns false.

func Nil

func Nil(t tester.T, have any, opts ...check.Option) bool

Nil asserts "have" is nil. Returns true if it is, otherwise marks the test as failed, writes error message to test log and returns false.

func NoDirExist

func NoDirExist(t tester.T, pth string, opts ...check.Option) bool

NoDirExist asserts "pth" points to not existing directory. It fails if the path points to an existing filesystem entry. Returns true on success, otherwise marks the test as failed, writes error message to test log and returns false.

func NoError

func NoError(t tester.T, err error, opts ...check.Option) bool

NoError asserts "err" is nil. Returns true if it is not, otherwise marks the test as failed, writes error message to test log and returns false.

func NoFileExist

func NoFileExist(t tester.T, pth string, opts ...check.Option) bool

NoFileExist asserts "pth" points to not existing file. It fails if the path points to an existing filesystem entry. Returns true on success, otherwise marks the test as failed, writes error message to test log and returns false.

func NoPanic

func NoPanic(t tester.T, fn check.TestFunc, opts ...check.Option) bool

NoPanic asserts "fn" does not panic. Returns true if it did not panic, otherwise marks the test as failed, writes error message to test log and returns false.

func NotContain

func NotContain(t tester.T, want, have string, opts ...check.Option) bool

NotContain asserts "want" is not a substring of "have". Returns true if it's not, otherwise marks the test as failed, writes error message to test log and returns false.

func NotEmpty

func NotEmpty(t tester.T, have any, opts ...check.Option) bool

NotEmpty asserts "have" is not empty. Returns true if it is not, otherwise marks the test as failed, writes error message to test log and returns false.

See check.Empty for list of values which are considered empty.

func NotEqual

func NotEqual(t tester.T, want, have any, opts ...check.Option) bool

NotEqual asserts both values are not equal. Returns true if they are not, otherwise marks the test as failed, writes error message to test log and returns false.

func NotNil

func NotNil(t tester.T, have any, opts ...check.Option) bool

NotNil asserts "have" is not nil. Returns true if it is not, otherwise marks the test as failed, writes error message to test log and returns false.

func NotSame

func NotSame(t tester.T, want, have any, opts ...check.Option) bool

NotSame asserts "want" and "have" are generic pointers and that both do not reference the same object. Returns true if they are not, otherwise marks the test as failed, writes error message to test log and returns false.

Both arguments must be pointer variables. Pointer variable sameness is determined based on the equality of both type and value.

func NotZero

func NotZero(t tester.T, have any, opts ...check.Option) bool

NotZero asserts "have" is not the zero value for its type. Returns true if it is not, otherwise marks the test as failed, writes error message to test log and returns false.

func Panic

func Panic(t tester.T, fn check.TestFunc, opts ...check.Option) bool

Panic asserts "fn" panics. Returns true if it panicked, otherwise marks the test as failed, writes error message to test log and returns false.

func PanicContain

func PanicContain(t tester.T, want string, fn check.TestFunc, opts ...check.Option) bool

PanicContain asserts "fn" panics, and the recovered panic value represented as a string contains "want". Returns true if it panics and does contain wanted string, otherwise marks the test as failed, writes error message to test log and returns false.

func PanicMsg

func PanicMsg(t tester.T, fn check.TestFunc, opts ...check.Option) *string

PanicMsg asserts "fn" panics, and returns the recovered panic value represented as a string. If function did not panic it marks the test as failed and writes error message to test log.

func Recent

func Recent(t tester.T, have any, opts ...check.Option) bool

Recent asserts "have" is within check.Options.Recent from time.Now. Returns nil if it is, otherwise marks the test as failed, writes error message to test log and returns false.

The "have" may represent date in form of a string, int, int64 or time.Time. For string representations the check.Options.TimeFormat is used during parsing and the returned date is always in UTC. The int and int64 types are interpreted as Unix Timestamp and the date returned is also in UTC.

func Regexp

func Regexp(t tester.T, want, have any, opts ...check.Option) bool

Regexp asserts that "want" regexp matches a string representation of "have. Returns true if it is, otherwise marks the test as failed, writes error message to test log and returns false.

The "want" can be either regular expression string or instance of regexp.Regexp. The fmt.Sprint s used to get string representation of have argument.

func Same

func Same(t tester.T, want, have any, opts ...check.Option) bool

Same asserts "want" and "have" are generic pointers and that both reference the same object. Returns true if they are, otherwise marks the test as failed, writes error message to test log and returns false.

Both arguments must be pointer variables. Pointer variable sameness is determined based on the equality of both type and value.

func SliceSubset

func SliceSubset[T comparable](t tester.T, want, have []T, opts ...check.Option) bool

SliceSubset checks the "want" is a subset "have". In other words all values in "want" slice must be in "have" slice. Returns nil if they are, otherwise returns an error with a message indicating the expected and actual values.

func Time

func Time(t tester.T, want, have any, opts ...check.Option) bool

Time asserts "want" and "have" dates are equal. Returns true if they are, otherwise marks the test as failed, writes error message to test log and returns false.

The "want" and "have" might be date representations in form of string, int, int64 or time.Time. For string representations the [Options.TimeFormat] is used during parsing and the returned date is always in UTC. The int and int64 types are interpreted as Unix Timestamp and the date returned is also in UTC.

func True

func True(t tester.T, have bool, opts ...check.Option) bool

True asserts "have" is true. Returns true if it's, otherwise marks the test as failed, writes error message to test log and returns false.

func Type

func Type(t tester.T, want, have any, opts ...check.Option) bool

Type asserts that both arguments are of the same type. Returns true if they are, otherwise marks the test as failed, writes error message to test log and returns false.

func Within

func Within(t tester.T, want, within, have any, opts ...check.Option) bool

Within asserts "want" and "have" dates are equal "within" given duration. Returns true if they are, otherwise marks the test as failed, writes error message to test log and returns false.

The "want" and "have" might be date representations in form of string, int, int64 or time.Time. For string representations the [Options.TimeFormat] is used during parsing and the returned date is always in UTC. The int and int64 types are interpreted as Unix Timestamp and the date returned is also in UTC.

The "within" might be duration representation in form of string, int, int64 or time.Duration.

func Zero

func Zero(t tester.T, have any, opts ...check.Option) bool

Zero asserts "have" is the zero value for its type. Returns true if it is, otherwise marks the test as failed, writes error message to test log and returns false.

func Zone

func Zone(t tester.T, want, have *time.Location, opts ...check.Option) bool

Zone asserts "want" and "have" timezones are equal. Returns true if they are, otherwise marks the test as failed, writes error message to test log and returns false.

Types

This section is empty.

Jump to

Keyboard shortcuts

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