An assertion package with a minimal API, yet powerful enough to cover most use cases.
The assert
package is designed to provide a more configurable and type-safe alternative to the popular testify/assert
package.
Have you ever struggled with comparing complex structs in your tests? One that use decimal.Decimal
, time.Time
, or uuid.UUID
types? Or perhaps you wanted to ignore automatically generated fields, such as ID
or CreatedAt
, in your struct comparisons?
assert
allows for more flexible assertions, such as ignoring unexported fields or skipping empty fields in struct comparisons.
package main
import (
"errors"
"fmt"
"io"
"io/fs"
"testing"
"github.com/krhubert/assert"
)
func TestXYZ(t *testing.T) {
// assert checks if value implements Equal() bool method
// and uses it to compare values. This makes it possible
// to compare e.g. time.Time values.
now := time.Now()
assert.Equal(t, now, now)
// assert is type safe, so this will not compile
// assert.Equal(t, 1, "1")
// assert do not compare pointers, but values they point to
a, b := 1, 1
assert.Equal(t, &a, &b)
// assert checks for errors
assert.Error(t, errors.New("error"))
assert.NoError(t, nil)
// assert checks if error contains a target value
// like string, error or struct
err := fmt.Errorf(
"closed socket: %w %w",
io.EOF,
&fs.PathError{Op: "read", Path: "socket", Err: io.ErrClosedPipe},
)
assert.ErrorContains(t, err, "closed socket")
assert.ErrorContains(t, err, io.EOF)
var pathError *fs.PathError
assert.ErrorContains(atb, err, &pathError)
// assert checks if function panics or not
assert.Panic(t, func() { panic(0) })
assert.NotPanic(t, func() { })
// assert can be used to check errors in defer functions
defer assert.Defer(t, func() error { return file.Close() })()
// assert can be used to check if a value is of a specific type
gs := TypeAssert[fmt.GoStringer](t, time.Time{})
}
package main
import (
"errors"
"fmt"
"io"
"io/fs"
"testing"
_ "github.com/mattn/go-sqlite3"
"go.uber.org/mock/gomock"
"github.com/krhubert/assert"
)
type ExampleTestSuite struct {
assert.Suite
i int
ctrl *gomock.Controller
db *sql.DB
}
func (s *ExampleTestSuite) Setup(t *testing.T) {
s.i = 4
s.ctrl = gomock.NewController(t)
db, err := sql.Open("sqlite3", ":memory:")
assert.NoError(t, err)
s.db = db
}
func (s *ExampleTestSuite) Teardown(t *testing.T) {
s.i = 0
assert.NoError(t, s.db.Close())
}
func TestExample(t *testing.T) {
ts := assert.Setup[ExampleTestSuite](t)
row := ts.db.QueryRow("select date()")
var date string
assert.NoError(ts, row.Scan(&date))
assert.NoError(ts, row.Err())
}
package assert
import (
"testing"
"time"
"github.com/google/uuid"
"github.com/shopspring/decimal"
"github.com/stretchr/testify/require"
)
func TestExampleEqual(t *testing.T) {
type User struct {
Id uuid.UUID
Email string
CreatedAt time.Time
Balance decimal.Decimal
active bool
}
loc, _ := time.LoadLocation("Europe/Warsaw")
// db.CreateUser("[email protected]")
createdAt := time.Now()
user := User{
Id: uuid.New(),
Email: "[email protected]",
CreatedAt: createdAt,
Balance: decimal.NewFromFloat(1),
active: true,
}
want := User{
Email: "[email protected]",
CreatedAt: createdAt.In(loc),
Balance: decimal.RequireFromString("1"),
}
}
Running go test
on:
Assert | Testify |
---|---|
assert.Equal(t, user, want, IgnoreUnexported(), SkipEmptyFields())
|
require.Equal(t, user, want)
|