assert

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Apr 9, 2025 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package assert provides a collection of assertion helpers designed to integrate seamlessly with the Go standard testing package. It aims to improve the readability and expressiveness of test code.

It has been written as an alternative to the testify package but it's not a drop-in replacement:

  • it supports most basic assertions
  • it's type-safe
  • it has far less features than testify
  • it does not support advanced diffs - use github.com/google/go-cmp for that

Key features include:

  • Type-safe comparisons using generics (e.g., assert.Greater, assert.Equal).
  • Checks for nil, errors, boolean conditions.
  • Collection assertions (Contains, Empty, Len, ElementsMatch).
  • Panic detection (Panics, NotPanics).
  • Time assertions (TimeEqual, TimeBefore, TimeAfter, WithinDuration).
  • Floating-point comparisons with delta for handling precision issues.
  • Support for custom failure messages with optional formatting.
  • Integration with t.Helper() for cleaner test failure reporting.
  • Consistent error formatting with file and line information.
  • Optional stack traces on failure for debugging complex call paths.

It draws inspiration from:

Examples

Basic usage:

func TestSomething(t *testing.T) {
    result := Calculate()
    assert.Equal(t, result, 42)
    assert.NoError(t, err)
}

Custom Error Messages:

assert.Equal(t, got, want, "calculation with input %d failed", input)

Collection Assertions:

values := []int{1, 2, 3}
assert.Contains(t, values, 2)
assert.Len(t, values, 3)

Error Handling:

err := doSomething()
if assert.Error(t, err) {
	assert.ErrorIs(t, err, ErrNotFound)
}

Time Assertions:

now := time.Now()
later := now.Add(time.Hour)
assert.TimeAfter(t, later, now)
assert.WithinDuration(t, eventTime, expectedTime, 5 * time.Second)

Floating-Point Comparisons:

assert.InDelta(t, calculatedValue, expectedValue, 0.001)

Diffs

The `Equal` function supports diffs when the `DiffsEnabled` global variable is set to true (default). This feature can be useful for debugging and understanding the differences between expected and actual values. That said, the implementation is simple and does not support complex types or nested structures. It's based on JSON serialization and comparison and thus might fail for unexported fields, channels or functions. Diff output uses the Myers diff algorithm.

To disable diffs, set the `DiffsEnabled` global variable to false.

Stack Traces

On assertion failure, an optional stack trace can be included in the error output. This is controlled by the `StackTracesEnabled` global variable, which defaults to `false`.

Capturing stack traces incurs a performance cost due to the use of `runtime.Stack`. It's recommended to enable this feature primarily during debugging sessions when the context of the call path is needed to understand a complex failure.

Example: Enable stack traces (e.g., in TestMain or a specific test):

assert.StackTracesEnabled = true
assert.Equal(t, someComplexResult(), expectedValue) // Stack trace printed if this fails
assert.StackTracesEnabled = false // Optionally disable afterwards

**Special Case: `NotPanics`** Because unexpected panics are critical failures where the stack trace is essential for debugging, `assert.NotPanics` (and `require.NotPanics`) will **always** include a filtered stack trace in the error output when a panic occurs, regardless of the `StackTracesEnabled` setting.

The generated stack trace is filtered to remove internal frames from the Go runtime, testing framework, and the assertion library itself, focusing on the user's test code.

Assertions

All assertions accept a `testing.T` interface, the value(s) being tested, and optional message arguments. They report failures using t.Errorf.

Error reporting

The package leverages `t.Helper()` and includes detailed error reporting with file and line information for debugging when assertions fail. Failed assertions will include details about the values compared, specific error messages, optional diffs, and optional stack traces.

Halting on failure

A companion package 'require' provides the same assertions, but calls t.FailNow() to stop test execution immediately on failure.

Index

Constants

This section is empty.

Variables

View Source
var DiffsEnabled = true

DiffsEnabled indicates whether diffing is enabled for assertion errors.

View Source
var StackTracesEnabled = false

StackTracesEnabled indicates whether stack traces are enabled for assertion errors.

Functions

func Contains

func Contains(t testingT, collection any, element any, msgAndArgs ...any) bool

Contains asserts that a collection contains a specific element/substring. Supports: - string: checks for substring presence. - slice/array: checks for element presence using the internal 'equal' comparison. - map: checks for value presence using the internal 'equal' comparison (unlike ContainsKey which checks for keys).

func ContainsKey

func ContainsKey[K comparable, V any](t testingT, m map[K]V, key K, msgAndArgs ...any) bool

ContainsKey asserts that a map contains a specific key.

func ElementsMatch

func ElementsMatch[T comparable](t testingT, listA []T, listB []T, msgAndArgs ...any) bool

ElementsMatch asserts that the specified listA(array, slice...) is equal to specified listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, the number of appearances of each of them in both lists should match.

ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])

func Empty

func Empty(t testingT, data any, msgAndArgs ...any) bool

Empty asserts that a value is considered "empty". True for: nil pointers/interfaces/slices/maps/channels/funcs, zero values (0, "", false, zero structs), and zero-length slices/maps/arrays/strings/channels.

func Equal

func Equal[T any](t testingT, got T, want T, msgAndArgs ...any) bool

Equal asserts that the given values are equal. It doesn't create advanced diff output for complex types. Use something like github.com/google/go-cmp/cmp for more advanced diff output.

func Error

func Error(t testingT, got error, msgAndArgs ...any) bool

Error asserts that the given error is not nil.

func ErrorAs

func ErrorAs(t testingT, got error, targetPtr any, msgAndArgs ...any) bool

ErrorAs asserts that the error 'got' can be assigned to the type pointed to by `targetPtr`using `errors.As`. It follows the chain of wrapped errors and assigns the matching error to `*targetPtr` if found. `targetPtr` must be a non-nil pointer to either an interface type or a concrete type that implements error.

func ErrorIs

func ErrorIs(t testingT, got error, target error, msgAndArgs ...any) bool

ErrorIs asserts that the error 'got' matches the target error 'target' using errors.Is. It follows the chain of wrapped errors.

func False

func False(t testingT, got bool, msgAndArgs ...any) bool

False asserts that the given boolean value is false.

func Greater

func Greater[T cmp.Ordered](t testingT, got T, threshold T, msgAndArgs ...any) bool

Greater asserts that 'got' is strictly greater than 'threshold'. Requires types compatible with cmp.Ordered (numbers, strings).

func GreaterOrEqual

func GreaterOrEqual[T cmp.Ordered](t testingT, got T, threshold T, msgAndArgs ...any) bool

GreaterOrEqual asserts that 'got' is greater than or equal to 'threshold'. Requires types compatible with cmp.Ordered.

func InDelta

func InDelta[T ~float32 | ~float64](t testingT, got T, want T, delta T, msgAndArgs ...any) bool

InDelta asserts that the given values are within delta.

func Len

func Len(t testingT, data any, expectedLen int, msgAndArgs ...any) bool

Len asserts that a collection (slice, map, array, string, channel) has a specific length.

func Less

func Less[T cmp.Ordered](t testingT, got T, threshold T, msgAndArgs ...any) bool

Less asserts that 'got' is strictly less than 'threshold'. Requires types compatible with cmp.Ordered.

func LessOrEqual

func LessOrEqual[T cmp.Ordered](t testingT, got T, threshold T, msgAndArgs ...any) bool

LessOrEqual asserts that 'got' is less than or equal to 'threshold'. Requires types compatible with cmp.Ordered.

func Negative

func Negative[T cmp.Ordered](t testingT, got T, msgAndArgs ...any) bool

Negative asserts that 'got' is less than zero. Requires types compatible with cmp.Ordered.

func Nil

func Nil(t testingT, data any, msgAndArgs ...any) bool

Nil asserts that the given value is nil.

func NoError

func NoError(t testingT, got error, msgAndArgs ...any) bool

NoError asserts that the given error is nil. Opposite of Error.

func NotContains

func NotContains(t testingT, collection any, element any, msgAndArgs ...any) bool

NotContains asserts that a collection does not contain a specific element/substring. Opposite of Contains. Supports the same types as Contains.

func NotContainsKey

func NotContainsKey[K comparable, V any](t testingT, m map[K]V, key K, msgAndArgs ...any) bool

NotContainsKey asserts that a map does not contain a specific key. Opposite of ContainsKey.

func NotEmpty

func NotEmpty(t testingT, data any, msgAndArgs ...any) bool

NotEmpty asserts that a value is not considered "empty". Opposite of Empty.

func NotEqual

func NotEqual[T any](t testingT, got T, want T, msgAndArgs ...any) bool

NotEqual asserts that the given values are not equal. It doesn't create advanced diff output for complex types. Use something like github.com/google/go-cmp/cmp for more advanced diff output. Opposite of Equal.

func NotInDelta

func NotInDelta[T ~float32 | ~float64](t testingT, got T, want T, delta T, msgAndArgs ...any) bool

NotInDelta asserts that the given values are not within delta. Opposite of InDelta.

func NotNil

func NotNil(t testingT, data any, msgAndArgs ...any) bool

NotNil asserts that the given value is not nil. Opposite of Nil.

func NotPanics

func NotPanics(t testingT, f func(), msgAndArgs ...any) bool

NotPanics asserts that the code inside the specified function doesn't panic.

func NotZero

func NotZero(t testingT, data any, msgAndArgs ...any) bool

NotZero asserts that a value is not the zero value for its type. Opposite of Zero.

func Panics

func Panics(t testingT, f func(), msgAndArgs ...any) (didPanic bool, panicValue any)

Panics asserts that the code inside the specified function panics.

func Positive

func Positive[T cmp.Ordered](t testingT, got T, msgAndArgs ...any) bool

Positive asserts that 'got' is greater than zero. Requires types compatible with cmp.Ordered.

func TimeAfter

func TimeAfter(t testingT, got, threshold time.Time, msgAndArgs ...any) bool

TimeAfter asserts that a time is after a threshold time

func TimeBefore

func TimeBefore(t testingT, got, threshold time.Time, msgAndArgs ...any) bool

TimeBefore asserts that a time is before a threshold time

func TimeEqual

func TimeEqual(t testingT, got, want time.Time, msgAndArgs ...any) bool

TimeEqual asserts that two times represent the same instant

func TimeEqualWithPrecision

func TimeEqualWithPrecision(t testingT, got, want time.Time, precision time.Duration, msgAndArgs ...any) bool

TimeEqualWithPrecision asserts that two times are equal within a certain precision

func True

func True(t testingT, got bool, msgAndArgs ...any) bool

True asserts that the given boolean value is true.

func WithinDuration

func WithinDuration(t testingT, got, want time.Time, delta time.Duration, msgAndArgs ...any) bool

WithinDuration asserts that two times are within a certain duration of each other

func WithinTime

func WithinTime(t testingT, got time.Time, start, end time.Time, msgAndArgs ...any) bool

WithinTime asserts that a time is within a given time window

func Zero

func Zero(t testingT, data any, msgAndArgs ...any) bool

Zero asserts that a value is the zero value for its type. Uses reflect.Value.IsZero(). Note this differs slightly from Empty for collections.e.g., Zero is false for an empty non-nil slice, but Empty is true.

Types

type AssertionContext

type AssertionContext struct {
	// Call site information
	File     string
	Line     int
	Function string
}

AssertionContext holds information about the context of an assertion

func NewAssertionContext

func NewAssertionContext(skip int) *AssertionContext

NewAssertionContext creates a new context by capturing the current call site

func (*AssertionContext) FileInfo

func (ctx *AssertionContext) FileInfo() string

FileInfo returns a string representation of the file and line information

type AssertionError

type AssertionError struct {
	// Message is the error message.
	Message string
	// PrimaryValue is the primary value being compared.
	PrimaryValue assertionValue
	// ComparisonValue is the value being compared against.
	ComparisonValue assertionValue
	// Error is the (optional) error that occurred during the assertion.
	Error error
	// ExtraValues are values that may be useful for debugging.
	ExtraValues []assertionValue
	// Diff is the (optional) difference between the primary and comparison values.
	Diff string
	// Details are details about the assertion error.
	Details []string
	// Stack trace - only populated when tests fail
	Stack string
}

AssertionError represents an assertion error.

filename.go:line_number (function_name): <Assertion Type>: <Primary Message>

<Primary Value Label>: <Primary Value Representation>
<Comparison Value Label>: <Comparison Value Representation>
Error: <Error Message>
ExtraValues:
  <Extra Value Label>: <Extra Value Representation>
Diff:
  <Diff Line 1>
  <Diff Line 2>
Details:
  <Detail Line 1>
  <Detail Line 2>

func (*AssertionError) Format

func (ae *AssertionError) Format(ctx *AssertionContext) string

Format handles all components of the message

Jump to

Keyboard shortcuts

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