Fix calls to t.Helper and optimize

This commit is contained in:
Nise Void 2020-05-27 19:56:16 +02:00
parent 0cc5d27277
commit 58bacd98ce
Signed by: NiseVoid
GPG Key ID: FBA14AC83EA602F3
2 changed files with 45 additions and 67 deletions

View File

@ -2,33 +2,32 @@ package assert
import ( import (
"reflect" "reflect"
"runtime"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
) )
// Assert is a helper for tests // Assert is a helper for tests
type Assert func(bool, ...interface{}) type Assert struct {
t T
}
// New returns a new Assert func (a Assert) f(ok bool, msg []interface{}, format string, extra ...interface{}) {
func New(t T) Assert {
a := func(ok bool, msg ...interface{}) {
if !ok { if !ok {
if format != `` {
msg = prepMsg(msg, format, extra...)
}
if msg == nil { if msg == nil {
msg = []interface{}{`Assertion failed`} msg = []interface{}{`Assertion failed`}
} }
msg = append(append([]interface{}{shell(1) + shell(97) + shell(41) + `FAIL!` + shell(0) + shell(1)}, msg...), shell(0), "\n") msg = append(append([]interface{}{shell(1) + shell(97) + shell(41) + `FAIL!` + shell(0) + shell(1)}, msg...), shell(0), "\n")
t.Helper() a.t.Helper()
t.Error(msg...) a.t.Error(msg...)
} }
} }
f := runtime.FuncForPC(reflect.ValueOf(a).Pointer()) // New returns a new Assert
ts[f] = t func New(t T) Assert {
a := Assert{t}
t.Cleanup(func() {
delete(ts, f)
})
return a return a
} }
@ -39,16 +38,14 @@ func New(t T) Assert {
// True asserts the given value is true // True asserts the given value is true
func (a Assert) True(actual bool, msg ...interface{}) { func (a Assert) True(actual bool, msg ...interface{}) {
t(a).Helper() a.t.Helper()
msg = prepMsg(msg, `Should be true, but it isn't`) a.f(actual, msg, `Should be true, but it isn't`)
a(actual, msg...)
} }
// False sserts the given value is false // False sserts the given value is false
func (a Assert) False(actual bool, msg ...interface{}) { func (a Assert) False(actual bool, msg ...interface{}) {
t(a).Helper() a.t.Helper()
msg = prepMsg(msg, `Should be false, but it isn't`) a.f(!actual, msg, `Should be false, but it isn't`)
a(!actual, msg...)
} }
///// Nil ///// ///// Nil /////
@ -69,87 +66,76 @@ func isNil(val interface{}) bool {
// Nil asserts the given value is nil // Nil asserts the given value is nil
func (a Assert) Nil(actual interface{}, msg ...interface{}) { func (a Assert) Nil(actual interface{}, msg ...interface{}) {
t(a).Helper() a.t.Helper()
msg = prepMsg(msg, `Should be nil, but got %#v`, actual) a.f(isNil(actual), msg, `Should be nil, but got %#v`, actual)
a(isNil(actual), msg...)
} }
// NotNil sserts the given value is not nil // NotNil sserts the given value is not nil
func (a Assert) NotNil(actual interface{}, msg ...interface{}) { func (a Assert) NotNil(actual interface{}, msg ...interface{}) {
t(a).Helper() a.t.Helper()
msg = prepMsg(msg, `Should not be nil, but it is`) a.f(!isNil(actual), msg, `Should not be nil, but it is`)
a(!isNil(actual), msg...)
} }
///// Errors ///// ///// Errors /////
// Error asserts the given error is not nil // Error asserts the given error is not nil
func (a Assert) Error(actual error, msg ...interface{}) { func (a Assert) Error(actual error, msg ...interface{}) {
t(a).Helper() a.t.Helper()
msg = prepMsg(msg, `Expected an error, but got nil`) a.f(actual != nil, msg, `Expected an error, but got nil`)
a(actual != nil, msg...)
} }
// NoError asserts the given error is not nil // NoError asserts the given error is not nil
func (a Assert) NoError(actual error, msg ...interface{}) { func (a Assert) NoError(actual error, msg ...interface{}) {
t(a).Helper() a.t.Helper()
msg = prepMsg(msg, `Expected no error, but got %#v`, actual) a.f(actual == nil, msg, `Expected no error, but got %#v`, actual)
a(actual == nil, msg...)
} }
///// Comparisons ///// ///// Comparisons /////
// Eq asserts the given values match // Eq asserts the given values match
func (a Assert) Eq(expected, actual interface{}, msg ...interface{}) { func (a Assert) Eq(expected, actual interface{}, msg ...interface{}) {
t(a).Helper() a.t.Helper()
if reflect.TypeOf(expected) != reflect.TypeOf(actual) { if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
msg = prepMsg(msg, `Expected %T(%#v), but got %T(%#v)`, expected, expected, actual, actual) a.f(false, msg, `Expected %T(%#v), but got %T(%#v)`, expected, expected, actual, actual)
a(false, msg...)
return return
} }
msg = prepMsg(msg, `Expected %#v, but got %#v`, expected, actual) a.f(expected == actual, msg, `Expected %#v, but got %#v`, expected, actual)
a(expected == actual, msg...)
} }
// Ne asserts the given values don't match // Ne asserts the given values don't match
func (a Assert) Ne(expected, actual interface{}, msg ...interface{}) { func (a Assert) Ne(expected, actual interface{}, msg ...interface{}) {
t(a).Helper() a.t.Helper()
msg = prepMsg(msg, `Should not be %#v, but it is`, expected) a.f(expected != actual, msg, `Should not be %#v, but it is`, expected)
a(expected != actual, msg...)
} }
///// Lists ///// ///// Lists /////
// Contains asserts the expected value is in the given list // Contains asserts the expected value is in the given list
func (a Assert) Contains(expected, list interface{}, msg ...interface{}) { func (a Assert) Contains(expected, list interface{}, msg ...interface{}) {
t(a).Helper() a.t.Helper()
rlist := reflect.ValueOf(list) rlist := reflect.ValueOf(list)
a(rlist.Kind() == reflect.Slice || rlist.Kind() == reflect.Array, `Can only call assert.Contains on a slice or array`) a.f(rlist.Kind() == reflect.Slice || rlist.Kind() == reflect.Array, nil, `Can only call assert.Contains on a slice or array`)
for i := 0; i < rlist.Len(); i++ { for i := 0; i < rlist.Len(); i++ {
if rlist.Index(i).Interface() == expected { if rlist.Index(i).Interface() == expected {
return return
} }
} }
msg = prepMsg(msg, `Expected %#v to be in %#v, but it isn't`, expected, list) a.f(false, msg, `Expected %#v to be in %#v, but it isn't`, expected, list)
a(false, msg...)
} }
// SameElements asserts the values have the same elements. It ignores the order of the elements // SameElements asserts the values have the same elements. It ignores the order of the elements
func (a Assert) SameElements(expected, actual interface{}, msg ...interface{}) { func (a Assert) SameElements(expected, actual interface{}, msg ...interface{}) {
t(a).Helper() a.t.Helper()
rexpected, ractual := reflect.ValueOf(expected), reflect.ValueOf(actual) rexpected, ractual := reflect.ValueOf(expected), reflect.ValueOf(actual)
a(rexpected.Kind() == reflect.Slice || rexpected.Kind() == reflect.Array, `Can only call assert.SameElements on a slice or array`) a.f(rexpected.Kind() == reflect.Slice || rexpected.Kind() == reflect.Array, nil, `Can only call assert.SameElements on a slice or array`)
a(ractual.Kind() == reflect.Slice || ractual.Kind() == reflect.Array, `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`)
msg = prepMsg(msg, `Expected elements of %#v to match %#v, but they don't`, expected, actual)
if rexpected.Len() != ractual.Len() { if rexpected.Len() != ractual.Len() {
a(false, msg...) a.f(false, msg, `Expected elements of %#v to match %#v, but they don't`, expected, actual)
return return
} }
@ -167,14 +153,15 @@ func (a Assert) SameElements(expected, actual interface{}, msg ...interface{}) {
return return
} }
a(false, msg...) a.f(false, msg, ``)
} }
func (a Assert) Cmp(expected, actual interface{}, opts ...cmp.Option) { func (a Assert) Cmp(expected, actual interface{}, opts ...cmp.Option) {
a.t.Helper()
diff := cmp.Diff(expected, actual, opts...) diff := cmp.Diff(expected, actual, opts...)
if diff == `` { if diff == `` {
return return
} }
a(false, "\n"+diff) a.f(false, nil, "\n"+diff)
} }

View File

@ -2,8 +2,6 @@ package assert
import ( import (
"fmt" "fmt"
"reflect"
"runtime"
"strconv" "strconv"
) )
@ -14,10 +12,3 @@ func prepMsg(msg []interface{}, format string, args ...interface{}) []interface{
func shell(i int) string { func shell(i int) string {
return "\x1B[" + strconv.Itoa(i) + "m" return "\x1B[" + strconv.Itoa(i) + "m"
} }
var ts = map[*runtime.Func]T{}
func t(a Assert) T {
f := runtime.FuncForPC(reflect.ValueOf(a).Pointer())
return ts[f]
}