Skip to content

pierrre/assert

Repository files navigation

Assert

Go test assertion library.

Go Reference

Features

Assertions

A simple assertion:

assert.Equal(t, value, 1)

By default, assertions fail with Fatal(). It can be changed with the Report() option:

assert.Equal(t, value, 1, assert.Report(t.Error))

The report message can be customized:

assert.Equal(t, value, 1, assert.MessageWrap("test"))

Why ?

This assertion library is an experiment to see if it is possible to do better than github.com/stretchr/testify, by using generics.

Here is an example of an issue with github.com/stretchr/testify:

func Test(t *testing.T) {
    value := getValue()
    require.Equal(t, 1, value)
}

func getValue() int64 {
    return 1
}

Surprinsingly, this test fails with this error:

Error: Not equal:
expected: int(1)
actual  : int64(1)

This issue is caused by the types, which are no identical (the 1 constant is an int and not an int64), and it's possible to fix it:

Convert the value to int64:

require.Equal(t, int64(1), value)

Use EqualValues() which converts the values to the same type:

require.EqualValues(t, 1, value)

But the internal implementation is not simple: it requires heavy usage of reflection, and the code is quite complex.

What if we could simply use the == operator ? This is the solution chosen by this library. It uses generics to do the comparison, and it works with any comparable type:

func Equal[T comparable](tb testing.TB, v1, v2 T, opts ...Option) bool {
    tb.Helper()
    ok := v1 == v2
    if !ok {
        Fail(...)
    }
    return ok
}
assert.Equal(t, 1, value)

The constant 1 is automatically converted to the type of the value variable without using reflection.

However, this approchach has a limitation: it requires to write a different assertion function for each "kind" (map, slice, etc...)

Customization

The default behavior can be customized:

FAQ

Why not use github.com/stretchr/testify ?

I think it's a great library, but I wanted to try something different. I also wanted to try generics, and to see if it was possible to make an assertion library without reflection.

Where are Nil() and NotNil() ?