assert/assert.go

177 lines
4.4 KiB
Go
Raw Normal View History

2018-12-03 22:40:34 +01:00
package assert
import (
"reflect"
2020-05-12 18:00:50 +02:00
"github.com/google/go-cmp/cmp"
2018-12-03 22:40:34 +01:00
)
// Assert is a helper for tests
2020-05-27 19:56:16 +02:00
type Assert struct {
t T
}
2018-12-03 22:40:34 +01:00
2020-05-27 19:56:16 +02:00
func (a Assert) f(ok bool, msg []interface{}, format string, extra ...interface{}) {
if !ok {
if format != `` {
msg = prepMsg(msg, format, extra...)
}
if msg == nil {
msg = []interface{}{`Assertion failed`}
2018-12-03 22:40:34 +01:00
}
2020-05-27 19:56:16 +02:00
msg = append(append([]interface{}{shell(1) + shell(97) + shell(41) + `FAIL!` + shell(0) + shell(1)}, msg...), shell(0), "\n")
a.t.Helper()
a.t.Error(msg...)
2018-12-03 22:40:34 +01:00
}
2020-05-27 19:56:16 +02:00
}
2018-12-03 22:40:34 +01:00
2020-05-27 19:56:16 +02:00
// New returns a new Assert
func New(t T) Assert {
a := Assert{t}
2018-12-03 22:40:34 +01:00
return a
}
// TODO: Panics, Len
///// Boolean /////
// True asserts the given value is true
func (a Assert) True(actual bool, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
a.f(actual, msg, `Should be true, but it isn't`)
2018-12-03 22:40:34 +01:00
}
// False sserts the given value is false
func (a Assert) False(actual bool, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
a.f(!actual, msg, `Should be false, but it isn't`)
2018-12-03 22:40:34 +01:00
}
///// Nil /////
func isNil(val interface{}) bool {
if val == nil {
return true
}
v := reflect.ValueOf(val)
switch v.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return v.IsNil()
}
return false
}
// Nil asserts the given value is nil
func (a Assert) Nil(actual interface{}, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
a.f(isNil(actual), msg, `Should be nil, but got %#v`, actual)
2018-12-03 22:40:34 +01:00
}
// NotNil sserts the given value is not nil
func (a Assert) NotNil(actual interface{}, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
a.f(!isNil(actual), msg, `Should not be nil, but it is`)
2018-12-03 22:40:34 +01:00
}
///// Errors /////
// Error asserts the given error is not nil
func (a Assert) Error(actual error, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
a.f(actual != nil, msg, `Expected an error, but got nil`)
2018-12-03 22:40:34 +01:00
}
// NoError asserts the given error is not nil
func (a Assert) NoError(actual error, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
a.f(actual == nil, msg, `Expected no error, but got %#v`, actual)
2018-12-03 22:40:34 +01:00
}
///// Comparisons /////
// Eq asserts the given values match
func (a Assert) Eq(expected, actual interface{}, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
2019-05-02 13:55:46 +02:00
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
2020-05-27 19:56:16 +02:00
a.f(false, msg, `Expected %T(%#v), but got %T(%#v)`, expected, expected, actual, actual)
2019-05-02 13:55:46 +02:00
return
}
2020-05-27 19:56:16 +02:00
a.f(expected == actual, msg, `Expected %#v, but got %#v`, expected, actual)
2018-12-03 22:40:34 +01:00
}
// Ne asserts the given values don't match
func (a Assert) Ne(expected, actual interface{}, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
a.f(expected != actual, msg, `Should not be %#v, but it is`, expected)
2018-12-03 22:40:34 +01:00
}
///// Lists /////
// Contains asserts the expected value is in the given list
func (a Assert) Contains(expected, list interface{}, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
2018-12-03 22:40:34 +01:00
rlist := reflect.ValueOf(list)
2020-05-27 19:56:16 +02:00
a.f(rlist.Kind() == reflect.Slice || rlist.Kind() == reflect.Array, nil, `Can only call assert.Contains on a slice or array`)
2018-12-03 22:40:34 +01:00
for i := 0; i < rlist.Len(); i++ {
if rlist.Index(i).Interface() == expected {
return
}
}
2020-05-27 19:56:16 +02:00
a.f(false, msg, `Expected %#v to be in %#v, but it isn't`, expected, list)
2018-12-03 22:40:34 +01:00
}
// SameElements asserts the values have the same elements. It ignores the order of the elements
func (a Assert) SameElements(expected, actual interface{}, msg ...interface{}) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
2018-12-03 22:40:34 +01:00
rexpected, ractual := reflect.ValueOf(expected), reflect.ValueOf(actual)
2020-05-27 19:56:16 +02:00
a.f(rexpected.Kind() == reflect.Slice || rexpected.Kind() == reflect.Array, nil, `Can only call assert.SameElements on a slice or array`)
a.f(ractual.Kind() == reflect.Slice || ractual.Kind() == reflect.Array, nil, `Can only call assert.SameElements on a slice or array`)
2018-12-03 22:40:34 +01:00
if rexpected.Len() != ractual.Len() {
2020-05-27 19:56:16 +02:00
a.f(false, msg, `Expected elements of %#v to match %#v, but they don't`, expected, actual)
2018-12-03 22:40:34 +01:00
return
}
var same int
for i := 0; i < rexpected.Len(); i++ {
for j := 0; j < ractual.Len(); j++ {
if rexpected.Index(i).Interface() == ractual.Index(j).Interface() {
same++
break
}
}
}
if same == rexpected.Len() {
return
}
2020-05-27 19:56:16 +02:00
a.f(false, msg, ``)
2018-12-03 22:40:34 +01:00
}
2020-05-12 18:00:50 +02:00
2020-06-12 19:35:26 +02:00
// Cmp assert wrapper for go-cmp
2020-05-12 18:00:50 +02:00
func (a Assert) Cmp(expected, actual interface{}, opts ...cmp.Option) {
2020-05-27 19:56:16 +02:00
a.t.Helper()
2020-05-12 18:00:50 +02:00
diff := cmp.Diff(expected, actual, opts...)
if diff == `` {
return
}
2020-05-27 19:56:16 +02:00
a.f(false, nil, "\n"+diff)
2020-05-12 18:00:50 +02:00
}
2020-06-12 19:35:26 +02:00
// NCmp assert wrapper for go-cmp but fails when !Equal
func (a Assert) NCmp(expected, actual interface{}, opts ...cmp.Option) {
a.t.Helper()
ok := cmp.Equal(expected, actual, opts...)
a.f(!ok, nil, `Should not be %#v, but it is`, expected)
}