-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtestr.go
142 lines (117 loc) · 3.27 KB
/
testr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Package testr provides a minimal extension to the standard library's testing.
package testr
import (
"errors"
"fmt"
"reflect"
)
// T represents testing.T.
type T interface {
Helper()
Logf(format string, args ...any)
Fail()
FailNow()
}
// Assertion provides assertion methods around T.
type Assertion struct{ t T }
// New returns a new Assertion given by T.
func New(t T) *Assertion {
return &Assertion{t}
}
func (assert *Assertion) checkNilT() {
if assert.t == nil {
panic("testr: T is nil")
}
}
// Equal asserts that the actual object are equal to the expected object.
// It can take options.
func (assert *Assertion) Equal(actual any, expected any, options ...Option) {
assert.checkNilT()
opt := newOption(assert.t, options...)
if reflect.DeepEqual(actual, expected) {
return
}
defer opt.fail()
assert.t.Helper()
assert.t.Logf("%s%s", ne(actual, expected), opt.message)
}
// ErrorIs asserts that the actual error are equal to the expected error.
// ErrorIs uses errors.Is so it can use any perks that errors.Is provides.
// It can take options.
func (assert *Assertion) ErrorIs(actual error, expected error, options ...Option) {
assert.checkNilT()
opt := newOption(assert.t, options...)
if errors.Is(actual, expected) {
return
}
defer opt.fail()
assert.t.Helper()
assert.t.Logf("%s%s", ne(actual, expected), opt.message)
}
// ErrorAs asserts that the actual error as the expected target.
// ErrorAs uses errors.As so it can use any perks that errors.As provides.
// It can take options.
func (assert *Assertion) ErrorAs(actual error, expected any, options ...Option) {
assert.checkNilT()
opt := newOption(assert.t, options...)
if errors.As(actual, expected) {
return
}
defer opt.fail()
assert.t.Helper()
assert.t.Logf("%s%s", ne(actual, raw(fmt.Sprintf("as(%T)", expected))), opt.message)
}
// Panic assert that the function is panic.
// It can take options.
func (assert *Assertion) Panic(f func(), options ...Option) {
assert.checkNilT()
opt := newOption(assert.t, options...)
defer func() {
v := recover()
if v != nil {
return
}
defer opt.fail()
assert.t.Helper()
assert.t.Logf("%s%s", ne(raw("func()"), raw("panic()")), opt.message)
}()
assert.t.Helper()
f()
}
// Must is a helper that wraps a call to a function returning error
// and panics if the error is non-nil. It is intended for use in variable
// initializations such as
//
// t := testr.MustV(json.Unmarshal(b, &v))
func Must(err error) {
if err != nil {
panic(err)
}
}
// MustV is a helper that wraps a call to a function returning (V, error)
// and panics if the error is non-nil. It is intended for use in variable
// initializations such as
//
// t := testr.MustV(json.Marshal(v))
func MustV[V any](v V, err error) V {
if err != nil {
panic(err)
}
return v
}
// ne returns a formatted string that tells the two objects are not equal.
func ne(actual, expected any) string {
return fmt.Sprintf("%s != expected:%s", val(actual), val(expected))
}
// raw represents a raw string that intended to be printed as is.
type raw string
// val returns a string of v with it's type or returns as is if v is raw.
func val(v any) string {
if err, ok := v.(error); ok {
return fmt.Sprintf("error(%v)", err)
}
if s, ok := v.(raw); ok {
return string(s)
}
return fmt.Sprintf("%#v", v)
}