Compare commits
No commits in common. "master" and "v0.0.2" have entirely different histories.
7 changed files with 68 additions and 300 deletions
114
assert.go
114
assert.go
|
@ -2,32 +2,28 @@ package assert
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
"github.com/google/go-cmp/cmp"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Assert is a helper for tests
|
// Assert is a helper for tests
|
||||||
type Assert struct {
|
type Assert func(bool, ...interface{})
|
||||||
t T
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a Assert) f(ok bool, msg []interface{}, format string, extra ...interface{}) {
|
// New returns a new Assert
|
||||||
|
func New(t *testing.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")
|
||||||
a.t.Helper()
|
t.Helper()
|
||||||
a.t.Error(msg...)
|
t.Error(msg...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new Assert
|
f := runtime.FuncForPC(reflect.ValueOf(a).Pointer())
|
||||||
func New(t T) Assert {
|
ts[f] = t
|
||||||
a := Assert{t}
|
|
||||||
|
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
@ -38,14 +34,16 @@ 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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
a.f(actual, msg, `Should be true, but it isn't`)
|
msg = prepMsg(msg, `Should be true, but it isn't`)
|
||||||
|
a(actual, msg...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// False asserts 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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
a.f(!actual, msg, `Should be false, but it isn't`)
|
msg = prepMsg(msg, `Should be false, but it isn't`)
|
||||||
|
a(!actual, msg...)
|
||||||
}
|
}
|
||||||
|
|
||||||
///// Nil /////
|
///// Nil /////
|
||||||
|
@ -66,76 +64,87 @@ 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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
a.f(isNil(actual), msg, `Should be nil, but got %#v`, actual)
|
msg = prepMsg(msg, `Should be nil, but got %#v`, actual)
|
||||||
|
|
||||||
|
a(isNil(actual), msg...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotNil asserts 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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
a.f(!isNil(actual), msg, `Should not be nil, but it is`)
|
msg = prepMsg(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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
a.f(actual != nil, msg, `Expected an error, but got nil`)
|
msg = prepMsg(msg, `Expected an error, but got nil`)
|
||||||
|
a(actual != nil, msg...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoError asserts the given error is 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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
a.f(actual == nil, msg, `Expected no error, but got %#v`, actual)
|
msg = prepMsg(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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
|
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
|
||||||
a.f(false, msg, `Expected %T(%#v), but got %T(%#v)`, expected, expected, actual, actual)
|
msg = prepMsg(msg, `Expected %T(%#v), but got %T(%#v)`, expected, expected, actual, actual)
|
||||||
|
a(false, msg...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
a.f(expected == actual, msg, `Expected %#v, but got %#v`, expected, actual)
|
msg = prepMsg(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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
a.f(expected != actual, msg, `Should not be %#v, but it is`, expected)
|
msg = prepMsg(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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
|
|
||||||
rlist := reflect.ValueOf(list)
|
rlist := reflect.ValueOf(list)
|
||||||
a.f(rlist.Kind() == reflect.Slice || rlist.Kind() == reflect.Array, nil, `Can only call assert.Contains on a slice or array`)
|
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++ {
|
for i := 0; i < rlist.Len(); i++ {
|
||||||
if rlist.Index(i).Interface() == expected {
|
if rlist.Index(i).Interface() == expected {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a.f(false, msg, `Expected %#v to be in %#v, but it isn't`, expected, list)
|
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
|
// 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{}) {
|
||||||
a.t.Helper()
|
t(a).Helper()
|
||||||
|
|
||||||
rexpected, ractual := reflect.ValueOf(expected), reflect.ValueOf(actual)
|
rexpected, ractual := reflect.ValueOf(expected), reflect.ValueOf(actual)
|
||||||
a.f(rexpected.Kind() == reflect.Slice || rexpected.Kind() == reflect.Array, nil, `Can only call assert.SameElements on a slice or array`)
|
a(rexpected.Kind() == reflect.Slice || rexpected.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`)
|
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() {
|
if rexpected.Len() != ractual.Len() {
|
||||||
a.f(false, msg, `Expected elements of %#v to match %#v, but they don't`, expected, actual)
|
a(false, msg...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,24 +162,5 @@ func (a Assert) SameElements(expected, actual interface{}, msg ...interface{}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
a.f(false, msg, ``)
|
a(false, msg...)
|
||||||
}
|
|
||||||
|
|
||||||
// Cmp assert wrapper for go-cmp
|
|
||||||
func (a Assert) Cmp(expected, actual interface{}, opts ...cmp.Option) {
|
|
||||||
a.t.Helper()
|
|
||||||
diff := cmp.Diff(expected, actual, opts...)
|
|
||||||
if diff == `` {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
a.f(false, nil, "\n"+diff)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
|
|
194
assert_test.go
194
assert_test.go
|
@ -1,194 +0,0 @@
|
||||||
package assert
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
// Slices
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
func TestSameElementsSlices(t *testing.T) {
|
|
||||||
assert := New(t)
|
|
||||||
ft, fa := newFakeT()
|
|
||||||
|
|
||||||
a, b := []int{1, 2}, []int{1, 2}
|
|
||||||
fa.SameElements(a, a)
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
fa.SameElements(a, b)
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
b = []int{2, 1}
|
|
||||||
fa.SameElements(b, a) // SameElements ignores order
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
b = []int{1, 2, 3}
|
|
||||||
fa.SameElements(b, a)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
|
|
||||||
b = []int{2, 3}
|
|
||||||
fa.SameElements(b, a)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCmpSlices(t *testing.T) {
|
|
||||||
assert := New(t)
|
|
||||||
ft, fa := newFakeT()
|
|
||||||
|
|
||||||
a, b := []int{1, 2}, []int{1, 2}
|
|
||||||
fa.Cmp(a, a)
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
fa.Cmp(a, b)
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
b = []int{2, 1}
|
|
||||||
fa.Cmp(a, b) // Cmp does not accept different order
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
|
|
||||||
b = []int{1, 2, 3}
|
|
||||||
fa.Cmp(a, b)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
|
|
||||||
b = []int{2, 3}
|
|
||||||
fa.Cmp(a, b)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
// Maps
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
func TestCmpMaps(t *testing.T) {
|
|
||||||
assert := New(t)
|
|
||||||
ft, fa := newFakeT()
|
|
||||||
|
|
||||||
a, b := map[int]int{1: 2, 3: 4}, map[int]int{1: 2, 3: 4}
|
|
||||||
fa.Cmp(a, a)
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
fa.Cmp(a, b)
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
b = map[int]int{1: 2, 3: 5}
|
|
||||||
fa.Cmp(a, b)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
|
|
||||||
b = map[int]int{1: 2, 3: 4, 5: 6}
|
|
||||||
fa.Cmp(a, b)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
|
|
||||||
b = map[int]int{1: 2}
|
|
||||||
fa.Cmp(a, b)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
// Pointers
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
func TestEqPointers(t *testing.T) {
|
|
||||||
assert := New(t)
|
|
||||||
ft, fa := newFakeT()
|
|
||||||
|
|
||||||
var a, b int
|
|
||||||
fa.Eq(&a, &a)
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
fa.Eq(&a, &b)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
|
|
||||||
fa.Eq(&b, &a)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCmpPointers(t *testing.T) {
|
|
||||||
assert := New(t)
|
|
||||||
ft, fa := newFakeT()
|
|
||||||
|
|
||||||
type B struct {
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
type A struct {
|
|
||||||
B *B
|
|
||||||
}
|
|
||||||
|
|
||||||
fa.Cmp(A{B: &B{1}}, A{&B{1}})
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
fa.Cmp(A{B: &B{1}}, A{&B{2}})
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
|
|
||||||
fa.Cmp(A{B: &B{1}}, A{nil})
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
// Timezones
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
func mustLoadLocation(zone string) *time.Location {
|
|
||||||
loc, err := time.LoadLocation(zone)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return loc
|
|
||||||
}
|
|
||||||
|
|
||||||
var locAmsterdam = mustLoadLocation(`Europe/Amsterdam`)
|
|
||||||
var locTokyo = mustLoadLocation(`Asia/Tokyo`)
|
|
||||||
|
|
||||||
func TestEqTimezones(t *testing.T) {
|
|
||||||
assert := New(t)
|
|
||||||
ft, fa := newFakeT()
|
|
||||||
|
|
||||||
ti := time.Now()
|
|
||||||
ti, ti2 := ti.In(locAmsterdam), ti.In(locTokyo)
|
|
||||||
|
|
||||||
fa.Eq(ti, ti2)
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCmpTimezones(t *testing.T) {
|
|
||||||
assert := New(t)
|
|
||||||
ft, fa := newFakeT()
|
|
||||||
|
|
||||||
type A struct {
|
|
||||||
Time time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
ti := time.Now()
|
|
||||||
ti2 := ti.In(time.UTC)
|
|
||||||
fa.Cmp(&A{ti}, &A{ti2})
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
ti2 = ti.In(locAmsterdam)
|
|
||||||
fa.Cmp(&A{ti}, &A{ti2})
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
ti = ti.In(locTokyo)
|
|
||||||
fa.Cmp(&A{ti}, &A{ti2})
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
ti2 = ti2.Add(time.Second)
|
|
||||||
fa.Cmp(&A{ti}, &A{ti2})
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNCmp(t *testing.T) {
|
|
||||||
assert := New(t)
|
|
||||||
ft, fa := newFakeT()
|
|
||||||
|
|
||||||
type A struct {
|
|
||||||
S string
|
|
||||||
}
|
|
||||||
|
|
||||||
fa.NCmp(A{"not"}, A{"equal"})
|
|
||||||
assert.False(ft.GotError())
|
|
||||||
|
|
||||||
fa.NCmp(A{"equal"}, A{"equal"})
|
|
||||||
assert.True(ft.GotError())
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package assert
|
|
||||||
|
|
||||||
type fakeT struct {
|
|
||||||
gotError bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFakeT() (*fakeT, Assert) {
|
|
||||||
var ft fakeT
|
|
||||||
return &ft, New(&ft)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *fakeT) Error(_ ...interface{}) {
|
|
||||||
t.gotError = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (_ *fakeT) Helper() {}
|
|
||||||
|
|
||||||
func (t *fakeT) GotError() bool {
|
|
||||||
r := t.gotError
|
|
||||||
t.gotError = false
|
|
||||||
|
|
||||||
return r
|
|
||||||
}
|
|
5
go.mod
5
go.mod
|
@ -1,5 +0,0 @@
|
||||||
module git.fuyu.moe/Fuyu/assert
|
|
||||||
|
|
||||||
go 1.14
|
|
||||||
|
|
||||||
require github.com/google/go-cmp v0.4.0
|
|
3
go.sum
3
go.sum
|
@ -1,3 +0,0 @@
|
||||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
10
helper.go
10
helper.go
|
@ -2,7 +2,10 @@ package assert
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func prepMsg(msg []interface{}, format string, args ...interface{}) []interface{} {
|
func prepMsg(msg []interface{}, format string, args ...interface{}) []interface{} {
|
||||||
|
@ -12,3 +15,10 @@ 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]*testing.T{}
|
||||||
|
|
||||||
|
func t(a Assert) *testing.T {
|
||||||
|
f := runtime.FuncForPC(reflect.ValueOf(a).Pointer())
|
||||||
|
return ts[f]
|
||||||
|
}
|
||||||
|
|
7
type.go
7
type.go
|
@ -1,7 +0,0 @@
|
||||||
package assert
|
|
||||||
|
|
||||||
// T is an interface of what we use from testing.T
|
|
||||||
type T interface {
|
|
||||||
Error(...interface{})
|
|
||||||
Helper()
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue