Go test assertion library.
- Test assertion (equal, comparison, nil, empty, length, error, etc...)
- No reflection (uses generics)
- Customization (print and compare values)
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"))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...)
The default behavior can be customized:
DeepEqualerallows to customize how values are compared withDeepEqual().ValueStringerallows to customize how values are printed.ErrorStringerallows to customize how errors are printed.
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.
- For slices use SliceNil() and SliceNotNil()
- For maps use MapNil() and MapNotNil()
- For comparable types use Zero() and NotZero()