1 package assert
2
3 import (
4 "fmt"
5 "os"
6 "testing"
7
8 gocmp "github.com/google/go-cmp/cmp"
9 "gotest.tools/v3/assert/cmp"
10 )
11
12 type fakeTestingT struct {
13 failNowed bool
14 failed bool
15 msgs []string
16 }
17
18 func (f *fakeTestingT) FailNow() {
19 f.failNowed = true
20 }
21
22 func (f *fakeTestingT) Fail() {
23 f.failed = true
24 }
25
26 func (f *fakeTestingT) Log(args ...interface{}) {
27 f.msgs = append(f.msgs, fmt.Sprint(args...))
28 }
29
30 func (f *fakeTestingT) Helper() {}
31
32 func TestAssert_WithBinaryExpression_Failures(t *testing.T) {
33 t.Run("equal", func(t *testing.T) {
34 fakeT := &fakeTestingT{}
35 Assert(fakeT, 1 == 6)
36 expectFailNowed(t, fakeT, "assertion failed: 1 is not 6")
37 })
38 t.Run("not equal", func(t *testing.T) {
39 fakeT := &fakeTestingT{}
40 a := 1
41 Assert(fakeT, a != 1)
42 expectFailNowed(t, fakeT, "assertion failed: a is 1")
43 })
44 t.Run("greater than", func(t *testing.T) {
45 fakeT := &fakeTestingT{}
46 Assert(fakeT, 1 > 5)
47 expectFailNowed(t, fakeT, "assertion failed: 1 is <= 5")
48 })
49 t.Run("less than", func(t *testing.T) {
50 fakeT := &fakeTestingT{}
51 Assert(fakeT, 5 < 1)
52 expectFailNowed(t, fakeT, "assertion failed: 5 is >= 1")
53 })
54 t.Run("greater than or equal", func(t *testing.T) {
55 fakeT := &fakeTestingT{}
56 Assert(fakeT, 1 >= 5)
57 expectFailNowed(t, fakeT, "assertion failed: 1 is less than 5")
58 })
59 t.Run("less than or equal", func(t *testing.T) {
60 fakeT := &fakeTestingT{}
61 Assert(fakeT, 6 <= 2)
62 expectFailNowed(t, fakeT, "assertion failed: 6 is greater than 2")
63 })
64 }
65
66 func TestAssertWithBoolIdent(t *testing.T) {
67 fakeT := &fakeTestingT{}
68
69 var ok bool
70 Assert(fakeT, ok)
71 expectFailNowed(t, fakeT, "assertion failed: ok is false")
72 }
73
74 func TestAssertWithBoolFailureNotEqual(t *testing.T) {
75 fakeT := &fakeTestingT{}
76
77 var err error
78 Assert(fakeT, err != nil)
79 expectFailNowed(t, fakeT, "assertion failed: err is nil")
80 }
81
82 func TestAssertWithBoolFailureNotTrue(t *testing.T) {
83 fakeT := &fakeTestingT{}
84
85 badNews := true
86 Assert(fakeT, !badNews)
87 expectFailNowed(t, fakeT, "assertion failed: badNews is true")
88 }
89
90 func TestAssertWithBoolFailureAndExtraMessage(t *testing.T) {
91 fakeT := &fakeTestingT{}
92
93 Assert(fakeT, 1 > 5, "sometimes things fail")
94 expectFailNowed(t, fakeT, "assertion failed: 1 is <= 5: sometimes things fail")
95 }
96
97 func TestAssertWithBoolSuccess(t *testing.T) {
98 fakeT := &fakeTestingT{}
99
100 Assert(fakeT, 1 < 5)
101 expectSuccess(t, fakeT)
102 }
103
104 func TestAssertWithBoolMultiLineFailure(t *testing.T) {
105 fakeT := &fakeTestingT{}
106
107 Assert(fakeT, func() bool {
108 for i := range []int{1, 2, 3, 4} {
109 _ = i
110 }
111 return false
112 }())
113 expectFailNowed(t, fakeT, `assertion failed: expression is false: func() bool {
114 for i := range []int{1, 2, 3, 4} {
115 _ = i
116 }
117 return false
118 }()`)
119 }
120
121 type exampleComparison struct {
122 success bool
123 message string
124 }
125
126 func (c exampleComparison) Compare() (bool, string) {
127 return c.success, c.message
128 }
129
130 func TestAssertWithComparisonSuccess(t *testing.T) {
131 fakeT := &fakeTestingT{}
132
133 cmp := exampleComparison{success: true}
134 Assert(fakeT, cmp.Compare)
135 expectSuccess(t, fakeT)
136 }
137
138 func TestAssertWithComparisonFailure(t *testing.T) {
139 fakeT := &fakeTestingT{}
140
141 cmp := exampleComparison{message: "oops, not good"}
142 Assert(fakeT, cmp.Compare)
143 expectFailNowed(t, fakeT, "assertion failed: oops, not good")
144 }
145
146 func TestAssertWithComparisonAndExtraMessage(t *testing.T) {
147 fakeT := &fakeTestingT{}
148
149 cmp := exampleComparison{message: "oops, not good"}
150 Assert(fakeT, cmp.Compare, "extra stuff %v", true)
151 expectFailNowed(t, fakeT, "assertion failed: oops, not good: extra stuff true")
152 }
153
154 type customError struct {
155 field bool
156 }
157
158 func (e *customError) Error() string {
159
160
161 e.field = true
162 return "custom error"
163 }
164
165 func TestNilError(t *testing.T) {
166 t.Run("nil interface", func(t *testing.T) {
167 fakeT := &fakeTestingT{}
168 var err error
169 NilError(fakeT, err)
170 expectSuccess(t, fakeT)
171 })
172
173 t.Run("nil literal", func(t *testing.T) {
174 fakeT := &fakeTestingT{}
175 NilError(fakeT, nil)
176 expectSuccess(t, fakeT)
177 })
178
179 t.Run("interface with non-nil type", func(t *testing.T) {
180 fakeT := &fakeTestingT{}
181 var customErr *customError
182 NilError(fakeT, customErr)
183 expected := "assertion failed: error is not nil: error has type *assert.customError"
184 expectFailNowed(t, fakeT, expected)
185 })
186
187 t.Run("non-nil error", func(t *testing.T) {
188 fakeT := &fakeTestingT{}
189 NilError(fakeT, fmt.Errorf("this is the error"))
190 expectFailNowed(t, fakeT, "assertion failed: error is not nil: this is the error")
191 })
192
193 t.Run("non-nil error with struct type", func(t *testing.T) {
194 fakeT := &fakeTestingT{}
195 err := structError{}
196 NilError(fakeT, err)
197 expectFailNowed(t, fakeT, "assertion failed: error is not nil: this is a struct")
198 })
199
200 t.Run("non-nil error with map type", func(t *testing.T) {
201 fakeT := &fakeTestingT{}
202 var err mapError
203 NilError(fakeT, err)
204 expectFailNowed(t, fakeT, "assertion failed: error is not nil: ")
205 })
206 }
207
208 type structError struct{}
209
210 func (structError) Error() string {
211 return "this is a struct"
212 }
213
214 type mapError map[int]string
215
216 func (m mapError) Error() string {
217 return m[0]
218 }
219
220 func TestCheckFailure(t *testing.T) {
221 fakeT := &fakeTestingT{}
222
223 if Check(fakeT, 1 == 2) {
224 t.Error("expected check to return false on failure")
225 }
226 expectFailed(t, fakeT, "assertion failed: 1 is not 2")
227 }
228
229 func TestCheckSuccess(t *testing.T) {
230 fakeT := &fakeTestingT{}
231
232 if !Check(fakeT, true) {
233 t.Error("expected check to return true on success")
234 }
235 expectSuccess(t, fakeT)
236 }
237
238 func TestCheckEqualFailure(t *testing.T) {
239 fakeT := &fakeTestingT{}
240
241 actual, expected := 5, 9
242 Check(fakeT, cmp.Equal(actual, expected))
243 expectFailed(t, fakeT, "assertion failed: 5 (actual int) != 9 (expected int)")
244 }
245
246 func TestCheck_MultipleFunctionsOnTheSameLine(t *testing.T) {
247 fakeT := &fakeTestingT{}
248
249 f := func(bool) {}
250 f(Check(fakeT, false))
251
252 expectFailed(t, fakeT,
253 "assertion failed: but assert failed to find the expression to print")
254 }
255
256 func TestEqualSuccess(t *testing.T) {
257 fakeT := &fakeTestingT{}
258
259 Equal(fakeT, 1, 1)
260 expectSuccess(t, fakeT)
261
262 Equal(fakeT, "abcd", "abcd")
263 expectSuccess(t, fakeT)
264 }
265
266 func TestEqualFailure(t *testing.T) {
267 fakeT := &fakeTestingT{}
268
269 actual, expected := 1, 3
270 Equal(fakeT, actual, expected)
271 expectFailNowed(t, fakeT, "assertion failed: 1 (actual int) != 3 (expected int)")
272 }
273
274 func TestEqualFailureTypes(t *testing.T) {
275 fakeT := &fakeTestingT{}
276
277 Equal(fakeT, 3, uint(3))
278 expectFailNowed(t, fakeT, `assertion failed: 3 (int) != 3 (uint)`)
279 }
280
281 func TestEqualFailureWithSelectorArgument(t *testing.T) {
282 fakeT := &fakeTestingT{}
283
284 type tc struct {
285 expected string
286 }
287 var testcase = tc{expected: "foo"}
288
289 Equal(fakeT, "ok", testcase.expected)
290 expectFailNowed(t, fakeT,
291 "assertion failed: ok (string) != foo (testcase.expected string)")
292 }
293
294 func TestEqualFailureWithIndexExpr(t *testing.T) {
295 fakeT := &fakeTestingT{}
296
297 expected := map[string]string{"foo": "bar"}
298 Equal(fakeT, "ok", expected["foo"])
299 expectFailNowed(t, fakeT,
300 `assertion failed: ok (string) != bar (expected["foo"] string)`)
301 }
302
303 func TestEqualFailureWithCallExprArgument(t *testing.T) {
304 fakeT := &fakeTestingT{}
305 ce := customError{}
306 Equal(fakeT, "", ce.Error())
307 expectFailNowed(t, fakeT,
308 "assertion failed: (string) != custom error (string)")
309 }
310
311 func TestAssertFailureWithOfflineComparison(t *testing.T) {
312 fakeT := &fakeTestingT{}
313 a := 1
314 b := 2
315
316 comparison := cmp.Equal(a, b)
317 Assert(fakeT, comparison)
318
319 expectFailNowed(t, fakeT, "assertion failed: 1 (int) != 2 (int)")
320 }
321
322 type testingT interface {
323 Errorf(msg string, args ...interface{})
324 Fatalf(msg string, args ...interface{})
325 }
326
327 func expectFailNowed(t testingT, fakeT *fakeTestingT, expected string) {
328 if ht, ok := t.(helperT); ok {
329 ht.Helper()
330 }
331 if fakeT.failed {
332 t.Errorf("should not have failed, got messages %s", fakeT.msgs)
333 }
334 if !fakeT.failNowed {
335 t.Fatalf("should have failNowed with message %s", expected)
336 }
337 if fakeT.msgs[0] != expected {
338 t.Fatalf("should have failure message %q, got %q", expected, fakeT.msgs[0])
339 }
340 }
341
342 func expectFailed(t testingT, fakeT *fakeTestingT, expected string) {
343 if ht, ok := t.(helperT); ok {
344 ht.Helper()
345 }
346 if fakeT.failNowed {
347 t.Errorf("should not have failNowed, got messages %s", fakeT.msgs)
348 }
349 if !fakeT.failed {
350 t.Fatalf("should have failed with message %s", expected)
351 }
352 if fakeT.msgs[0] != expected {
353 t.Fatalf("should have failure message %q, got %q", expected, fakeT.msgs[0])
354 }
355 }
356
357 func expectSuccess(t testingT, fakeT *fakeTestingT) {
358 if ht, ok := t.(helperT); ok {
359 ht.Helper()
360 }
361 if fakeT.failNowed {
362 t.Errorf("should not have failNowed, got messages %s", fakeT.msgs)
363 }
364 if fakeT.failed {
365 t.Errorf("should not have failed, got messages %s", fakeT.msgs)
366 }
367 }
368
369 type stub struct {
370 a string
371 b int
372 }
373
374 func TestDeepEqualSuccess(t *testing.T) {
375 actual := stub{"ok", 1}
376 expected := stub{"ok", 1}
377
378 fakeT := &fakeTestingT{}
379 DeepEqual(fakeT, actual, expected, gocmp.AllowUnexported(stub{}))
380 expectSuccess(t, fakeT)
381 }
382
383 func TestDeepEqualFailure(t *testing.T) {
384 actual := stub{"ok", 1}
385 expected := stub{"ok", 2}
386
387 fakeT := &fakeTestingT{}
388 DeepEqual(fakeT, actual, expected, gocmp.AllowUnexported(stub{}))
389 if !fakeT.failNowed {
390 t.Fatal("should have failNowed")
391 }
392 }
393
394 func TestErrorFailure(t *testing.T) {
395 t.Run("nil error", func(t *testing.T) {
396 fakeT := &fakeTestingT{}
397
398 var err error
399 Error(fakeT, err, "this error")
400 expectFailNowed(t, fakeT, "assertion failed: expected an error, got nil")
401 })
402 t.Run("different error", func(t *testing.T) {
403 fakeT := &fakeTestingT{}
404
405 err := fmt.Errorf("the actual error")
406 Error(fakeT, err, "this error")
407 expected := `assertion failed: expected error "this error", got "the actual error"`
408 expectFailNowed(t, fakeT, expected)
409 })
410 }
411
412 func TestErrorContainsFailure(t *testing.T) {
413 t.Run("nil error", func(t *testing.T) {
414 fakeT := &fakeTestingT{}
415
416 var err error
417 ErrorContains(fakeT, err, "this error")
418 expectFailNowed(t, fakeT, "assertion failed: expected an error, got nil")
419 })
420 t.Run("different error", func(t *testing.T) {
421 fakeT := &fakeTestingT{}
422
423 err := fmt.Errorf("the actual error")
424 ErrorContains(fakeT, err, "this error")
425 expected := `assertion failed: expected error to contain "this error", got "the actual error"`
426 expectFailNowed(t, fakeT, expected)
427 })
428 }
429
430 func TestErrorTypeFailure(t *testing.T) {
431 t.Run("nil error", func(t *testing.T) {
432 fakeT := &fakeTestingT{}
433
434 var err error
435 ErrorType(fakeT, err, os.IsNotExist)
436 expectFailNowed(t, fakeT, "assertion failed: error is nil, not os.IsNotExist")
437 })
438 t.Run("different error", func(t *testing.T) {
439 fakeT := &fakeTestingT{}
440
441 err := fmt.Errorf("the actual error")
442 ErrorType(fakeT, err, os.IsNotExist)
443 expected := `assertion failed: error is the actual error (*errors.errorString), not os.IsNotExist`
444 expectFailNowed(t, fakeT, expected)
445 })
446 }
447
448 func TestErrorIs(t *testing.T) {
449 t.Run("nil error", func(t *testing.T) {
450 fakeT := &fakeTestingT{}
451
452 var err error
453 ErrorIs(fakeT, err, os.ErrNotExist)
454 expected := `assertion failed: error is nil, not "file does not exist" (os.ErrNotExist)`
455 expectFailNowed(t, fakeT, expected)
456 })
457 t.Run("different error", func(t *testing.T) {
458 fakeT := &fakeTestingT{}
459
460 err := fmt.Errorf("the actual error")
461 ErrorIs(fakeT, err, os.ErrNotExist)
462 expected := `assertion failed: error is "the actual error", not "file does not exist" (os.ErrNotExist)`
463 expectFailNowed(t, fakeT, expected)
464 })
465 t.Run("same error", func(t *testing.T) {
466 fakeT := &fakeTestingT{}
467
468 err := fmt.Errorf("some wrapping: %w", os.ErrNotExist)
469 ErrorIs(fakeT, err, os.ErrNotExist)
470 expectSuccess(t, fakeT)
471 })
472 }
473
View as plain text