From 977c232584b31a9fe8fdd6f01282e4049effbb01 Mon Sep 17 00:00:00 2001 From: NiseVoid Date: Mon, 3 Dec 2018 22:40:34 +0100 Subject: [PATCH] Initial commit --- assert.go | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ helper.go | 24 ++++++++ 2 files changed, 184 insertions(+) create mode 100644 assert.go create mode 100644 helper.go diff --git a/assert.go b/assert.go new file mode 100644 index 0000000..c8c1675 --- /dev/null +++ b/assert.go @@ -0,0 +1,160 @@ +package assert + +import ( + "reflect" + "runtime" + "testing" +) + +// Assert is a helper for tests +type Assert func(bool, ...interface{}) + +// New returns a new Assert +func New(t *testing.T) Assert { + a := func(ok bool, msg ...interface{}) { + if !ok { + if msg == nil { + msg = []interface{}{`Assertion failed`} + } + msg = append(append([]interface{}{shell(1) + shell(97) + shell(41) + `FAIL!` + shell(0) + shell(1)}, msg...), shell(0), "\n") + t.Helper() + t.Error(msg...) + } + } + + f := runtime.FuncForPC(reflect.ValueOf(a).Pointer()) + ts[f] = t + + return a +} + +// TODO: Panics, Len + +///// Boolean ///// + +// True asserts the given value is true +func (a Assert) True(actual bool, msg ...interface{}) { + t(a).Helper() + msg = prepMsg(msg, `Should be true, but it isn't`) + a(actual, msg...) +} + +// False sserts the given value is false +func (a Assert) False(actual bool, msg ...interface{}) { + t(a).Helper() + msg = prepMsg(msg, `Should be false, but it isn't`) + a(!actual, msg...) +} + +///// 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{}) { + t(a).Helper() + msg = prepMsg(msg, `Should be nil, but it isn't`) + + a(isNil(actual), msg...) +} + +// NotNil sserts the given value is not nil +func (a Assert) NotNil(actual interface{}, msg ...interface{}) { + t(a).Helper() + msg = prepMsg(msg, `Should not be nil, but it is`) + + a(!isNil(actual), msg...) +} + +///// Errors ///// + +// Error asserts the given error is not nil +func (a Assert) Error(actual error, msg ...interface{}) { + t(a).Helper() + msg = prepMsg(msg, `Expected an error, but got nil`) + a(actual != nil, msg...) +} + +// NoError asserts the given error is not nil +func (a Assert) NoError(actual error, msg ...interface{}) { + t(a).Helper() + msg = prepMsg(msg, `Expected no error, but got %#v`, actual) + a(actual == nil, msg...) +} + +///// Comparisons ///// + +// Eq asserts the given values match +func (a Assert) Eq(expected, actual interface{}, msg ...interface{}) { + t(a).Helper() + msg = prepMsg(msg, `Expected %#v, but got %#v`, expected, actual) + a(expected == actual, msg...) +} + +// Ne asserts the given values don't match +func (a Assert) Ne(expected, actual interface{}, msg ...interface{}) { + t(a).Helper() + msg = prepMsg(msg, `Should not be %#v, but it is`, expected) + a(expected != actual, msg...) +} + +///// Lists ///// + +// Contains asserts the expected value is in the given list +func (a Assert) Contains(expected, list interface{}, msg ...interface{}) { + t(a).Helper() + + rlist := reflect.ValueOf(list) + a(rlist.Kind() == reflect.Slice || rlist.Kind() == reflect.Array, `Can only call assert.Contains on a slice or array`) + for i := 0; i < rlist.Len(); i++ { + if rlist.Index(i).Interface() == expected { + return + } + } + + msg = prepMsg(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 +func (a Assert) SameElements(expected, actual interface{}, msg ...interface{}) { + t(a).Helper() + + 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(ractual.Kind() == reflect.Slice || ractual.Kind() == reflect.Array, `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() { + a(false, msg...) + 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 + } + + a(false, msg...) +} diff --git a/helper.go b/helper.go new file mode 100644 index 0000000..67cc4a9 --- /dev/null +++ b/helper.go @@ -0,0 +1,24 @@ +package assert + +import ( + "fmt" + "reflect" + "runtime" + "strconv" + "testing" +) + +func prepMsg(msg []interface{}, format string, args ...interface{}) []interface{} { + return append(msg, "\n\n", fmt.Sprintf(format, args...)) +} + +func shell(i int) string { + return "\x1B[" + strconv.Itoa(i) + "m" +} + +var ts = map[*runtime.Func]*testing.T{} + +func t(a Assert) *testing.T { + f := runtime.FuncForPC(reflect.ValueOf(a).Pointer()) + return ts[f] +}