1package require
2
3import (
4	"encoding/json"
5	"errors"
6	"testing"
7	"time"
8)
9
10// AssertionTesterInterface defines an interface to be used for testing assertion methods
11type AssertionTesterInterface interface {
12	TestMethod()
13}
14
15// AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface
16type AssertionTesterConformingObject struct {
17}
18
19func (a *AssertionTesterConformingObject) TestMethod() {
20}
21
22// AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface
23type AssertionTesterNonConformingObject struct {
24}
25
26type MockT struct {
27	Failed bool
28}
29
30func (t *MockT) FailNow() {
31	t.Failed = true
32}
33
34func (t *MockT) Errorf(format string, args ...interface{}) {
35	_, _ = format, args
36}
37
38func TestImplements(t *testing.T) {
39
40	Implements(t, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject))
41
42	mockT := new(MockT)
43	Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject))
44	if !mockT.Failed {
45		t.Error("Check should fail")
46	}
47}
48
49func TestIsType(t *testing.T) {
50
51	IsType(t, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject))
52
53	mockT := new(MockT)
54	IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject))
55	if !mockT.Failed {
56		t.Error("Check should fail")
57	}
58}
59
60func TestEqual(t *testing.T) {
61
62	Equal(t, 1, 1)
63
64	mockT := new(MockT)
65	Equal(mockT, 1, 2)
66	if !mockT.Failed {
67		t.Error("Check should fail")
68	}
69
70}
71
72func TestNotEqual(t *testing.T) {
73
74	NotEqual(t, 1, 2)
75	mockT := new(MockT)
76	NotEqual(mockT, 2, 2)
77	if !mockT.Failed {
78		t.Error("Check should fail")
79	}
80}
81
82func TestExactly(t *testing.T) {
83
84	a := float32(1)
85	b := float32(1)
86	c := float64(1)
87
88	Exactly(t, a, b)
89
90	mockT := new(MockT)
91	Exactly(mockT, a, c)
92	if !mockT.Failed {
93		t.Error("Check should fail")
94	}
95}
96
97func TestNotNil(t *testing.T) {
98
99	NotNil(t, new(AssertionTesterConformingObject))
100
101	mockT := new(MockT)
102	NotNil(mockT, nil)
103	if !mockT.Failed {
104		t.Error("Check should fail")
105	}
106}
107
108func TestNil(t *testing.T) {
109
110	Nil(t, nil)
111
112	mockT := new(MockT)
113	Nil(mockT, new(AssertionTesterConformingObject))
114	if !mockT.Failed {
115		t.Error("Check should fail")
116	}
117}
118
119func TestTrue(t *testing.T) {
120
121	True(t, true)
122
123	mockT := new(MockT)
124	True(mockT, false)
125	if !mockT.Failed {
126		t.Error("Check should fail")
127	}
128}
129
130func TestFalse(t *testing.T) {
131
132	False(t, false)
133
134	mockT := new(MockT)
135	False(mockT, true)
136	if !mockT.Failed {
137		t.Error("Check should fail")
138	}
139}
140
141func TestContains(t *testing.T) {
142
143	Contains(t, "Hello World", "Hello")
144
145	mockT := new(MockT)
146	Contains(mockT, "Hello World", "Salut")
147	if !mockT.Failed {
148		t.Error("Check should fail")
149	}
150}
151
152func TestNotContains(t *testing.T) {
153
154	NotContains(t, "Hello World", "Hello!")
155
156	mockT := new(MockT)
157	NotContains(mockT, "Hello World", "Hello")
158	if !mockT.Failed {
159		t.Error("Check should fail")
160	}
161}
162
163func TestPanics(t *testing.T) {
164
165	Panics(t, func() {
166		panic("Panic!")
167	})
168
169	mockT := new(MockT)
170	Panics(mockT, func() {})
171	if !mockT.Failed {
172		t.Error("Check should fail")
173	}
174}
175
176func TestNotPanics(t *testing.T) {
177
178	NotPanics(t, func() {})
179
180	mockT := new(MockT)
181	NotPanics(mockT, func() {
182		panic("Panic!")
183	})
184	if !mockT.Failed {
185		t.Error("Check should fail")
186	}
187}
188
189func TestNoError(t *testing.T) {
190
191	NoError(t, nil)
192
193	mockT := new(MockT)
194	NoError(mockT, errors.New("some error"))
195	if !mockT.Failed {
196		t.Error("Check should fail")
197	}
198}
199
200func TestError(t *testing.T) {
201
202	Error(t, errors.New("some error"))
203
204	mockT := new(MockT)
205	Error(mockT, nil)
206	if !mockT.Failed {
207		t.Error("Check should fail")
208	}
209}
210
211func TestEqualError(t *testing.T) {
212
213	EqualError(t, errors.New("some error"), "some error")
214
215	mockT := new(MockT)
216	EqualError(mockT, errors.New("some error"), "Not some error")
217	if !mockT.Failed {
218		t.Error("Check should fail")
219	}
220}
221
222func TestEmpty(t *testing.T) {
223
224	Empty(t, "")
225
226	mockT := new(MockT)
227	Empty(mockT, "x")
228	if !mockT.Failed {
229		t.Error("Check should fail")
230	}
231}
232
233func TestNotEmpty(t *testing.T) {
234
235	NotEmpty(t, "x")
236
237	mockT := new(MockT)
238	NotEmpty(mockT, "")
239	if !mockT.Failed {
240		t.Error("Check should fail")
241	}
242}
243
244func TestWithinDuration(t *testing.T) {
245
246	a := time.Now()
247	b := a.Add(10 * time.Second)
248
249	WithinDuration(t, a, b, 15*time.Second)
250
251	mockT := new(MockT)
252	WithinDuration(mockT, a, b, 5*time.Second)
253	if !mockT.Failed {
254		t.Error("Check should fail")
255	}
256}
257
258func TestInDelta(t *testing.T) {
259
260	InDelta(t, 1.001, 1, 0.01)
261
262	mockT := new(MockT)
263	InDelta(mockT, 1, 2, 0.5)
264	if !mockT.Failed {
265		t.Error("Check should fail")
266	}
267}
268
269func TestZero(t *testing.T) {
270
271	Zero(t, "")
272
273	mockT := new(MockT)
274	Zero(mockT, "x")
275	if !mockT.Failed {
276		t.Error("Check should fail")
277	}
278}
279
280func TestNotZero(t *testing.T) {
281
282	NotZero(t, "x")
283
284	mockT := new(MockT)
285	NotZero(mockT, "")
286	if !mockT.Failed {
287		t.Error("Check should fail")
288	}
289}
290
291func TestJSONEq_EqualSONString(t *testing.T) {
292	mockT := new(MockT)
293	JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)
294	if mockT.Failed {
295		t.Error("Check should pass")
296	}
297}
298
299func TestJSONEq_EquivalentButNotEqual(t *testing.T) {
300	mockT := new(MockT)
301	JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
302	if mockT.Failed {
303		t.Error("Check should pass")
304	}
305}
306
307func TestJSONEq_HashOfArraysAndHashes(t *testing.T) {
308	mockT := new(MockT)
309	JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}",
310		"{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}")
311	if mockT.Failed {
312		t.Error("Check should pass")
313	}
314}
315
316func TestJSONEq_Array(t *testing.T) {
317	mockT := new(MockT)
318	JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)
319	if mockT.Failed {
320		t.Error("Check should pass")
321	}
322}
323
324func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) {
325	mockT := new(MockT)
326	JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)
327	if !mockT.Failed {
328		t.Error("Check should fail")
329	}
330}
331
332func TestJSONEq_HashesNotEquivalent(t *testing.T) {
333	mockT := new(MockT)
334	JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
335	if !mockT.Failed {
336		t.Error("Check should fail")
337	}
338}
339
340func TestJSONEq_ActualIsNotJSON(t *testing.T) {
341	mockT := new(MockT)
342	JSONEq(mockT, `{"foo": "bar"}`, "Not JSON")
343	if !mockT.Failed {
344		t.Error("Check should fail")
345	}
346}
347
348func TestJSONEq_ExpectedIsNotJSON(t *testing.T) {
349	mockT := new(MockT)
350	JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`)
351	if !mockT.Failed {
352		t.Error("Check should fail")
353	}
354}
355
356func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) {
357	mockT := new(MockT)
358	JSONEq(mockT, "Not JSON", "Not JSON")
359	if !mockT.Failed {
360		t.Error("Check should fail")
361	}
362}
363
364func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) {
365	mockT := new(MockT)
366	JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)
367	if !mockT.Failed {
368		t.Error("Check should fail")
369	}
370}
371
372func TestYAMLEq_EqualYAMLString(t *testing.T) {
373	mockT := new(MockT)
374	YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)
375	if mockT.Failed {
376		t.Error("Check should pass")
377	}
378}
379
380func TestYAMLEq_EquivalentButNotEqual(t *testing.T) {
381	mockT := new(MockT)
382	YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
383	if mockT.Failed {
384		t.Error("Check should pass")
385	}
386}
387
388func TestYAMLEq_HashOfArraysAndHashes(t *testing.T) {
389	mockT := new(MockT)
390	expected := `
391numeric: 1.5
392array:
393  - foo: bar
394  - 1
395  - "string"
396  - ["nested", "array", 5.5]
397hash:
398  nested: hash
399  nested_slice: [this, is, nested]
400string: "foo"
401`
402
403	actual := `
404numeric: 1.5
405hash:
406  nested: hash
407  nested_slice: [this, is, nested]
408string: "foo"
409array:
410  - foo: bar
411  - 1
412  - "string"
413  - ["nested", "array", 5.5]
414`
415	YAMLEq(mockT, expected, actual)
416	if mockT.Failed {
417		t.Error("Check should pass")
418	}
419}
420
421func TestYAMLEq_Array(t *testing.T) {
422	mockT := new(MockT)
423	YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)
424	if mockT.Failed {
425		t.Error("Check should pass")
426	}
427}
428
429func TestYAMLEq_HashAndArrayNotEquivalent(t *testing.T) {
430	mockT := new(MockT)
431	YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)
432	if !mockT.Failed {
433		t.Error("Check should fail")
434	}
435}
436
437func TestYAMLEq_HashesNotEquivalent(t *testing.T) {
438	mockT := new(MockT)
439	YAMLEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
440	if !mockT.Failed {
441		t.Error("Check should fail")
442	}
443}
444
445func TestYAMLEq_ActualIsSimpleString(t *testing.T) {
446	mockT := new(MockT)
447	YAMLEq(mockT, `{"foo": "bar"}`, "Simple String")
448	if !mockT.Failed {
449		t.Error("Check should fail")
450	}
451}
452
453func TestYAMLEq_ExpectedIsSimpleString(t *testing.T) {
454	mockT := new(MockT)
455	YAMLEq(mockT, "Simple String", `{"foo": "bar", "hello": "world"}`)
456	if !mockT.Failed {
457		t.Error("Check should fail")
458	}
459}
460
461func TestYAMLEq_ExpectedAndActualSimpleString(t *testing.T) {
462	mockT := new(MockT)
463	YAMLEq(mockT, "Simple String", "Simple String")
464	if mockT.Failed {
465		t.Error("Check should pass")
466	}
467}
468
469func TestYAMLEq_ArraysOfDifferentOrder(t *testing.T) {
470	mockT := new(MockT)
471	YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)
472	if !mockT.Failed {
473		t.Error("Check should fail")
474	}
475}
476
477func ExampleComparisonAssertionFunc() {
478	t := &testing.T{} // provided by test
479
480	adder := func(x, y int) int {
481		return x + y
482	}
483
484	type args struct {
485		x int
486		y int
487	}
488
489	tests := []struct {
490		name      string
491		args      args
492		expect    int
493		assertion ComparisonAssertionFunc
494	}{
495		{"2+2=4", args{2, 2}, 4, Equal},
496		{"2+2!=5", args{2, 2}, 5, NotEqual},
497		{"2+3==5", args{2, 3}, 5, Exactly},
498	}
499
500	for _, tt := range tests {
501		t.Run(tt.name, func(t *testing.T) {
502			tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y))
503		})
504	}
505}
506
507func TestComparisonAssertionFunc(t *testing.T) {
508	type iface interface {
509		Name() string
510	}
511
512	tests := []struct {
513		name      string
514		expect    interface{}
515		got       interface{}
516		assertion ComparisonAssertionFunc
517	}{
518		{"implements", (*iface)(nil), t, Implements},
519		{"isType", (*testing.T)(nil), t, IsType},
520		{"equal", t, t, Equal},
521		{"equalValues", t, t, EqualValues},
522		{"exactly", t, t, Exactly},
523		{"notEqual", t, nil, NotEqual},
524		{"notContains", []int{1, 2, 3}, 4, NotContains},
525		{"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset},
526		{"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset},
527		{"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch},
528		{"regexp", "^t.*y$", "testify", Regexp},
529		{"notRegexp", "^t.*y$", "Testify", NotRegexp},
530	}
531
532	for _, tt := range tests {
533		t.Run(tt.name, func(t *testing.T) {
534			tt.assertion(t, tt.expect, tt.got)
535		})
536	}
537}
538
539func ExampleValueAssertionFunc() {
540	t := &testing.T{} // provided by test
541
542	dumbParse := func(input string) interface{} {
543		var x interface{}
544		json.Unmarshal([]byte(input), &x)
545		return x
546	}
547
548	tests := []struct {
549		name      string
550		arg       string
551		assertion ValueAssertionFunc
552	}{
553		{"true is not nil", "true", NotNil},
554		{"empty string is nil", "", Nil},
555		{"zero is not nil", "0", NotNil},
556		{"zero is zero", "0", Zero},
557		{"false is zero", "false", Zero},
558	}
559
560	for _, tt := range tests {
561		t.Run(tt.name, func(t *testing.T) {
562			tt.assertion(t, dumbParse(tt.arg))
563		})
564	}
565}
566
567func TestValueAssertionFunc(t *testing.T) {
568	tests := []struct {
569		name      string
570		value     interface{}
571		assertion ValueAssertionFunc
572	}{
573		{"notNil", true, NotNil},
574		{"nil", nil, Nil},
575		{"empty", []int{}, Empty},
576		{"notEmpty", []int{1}, NotEmpty},
577		{"zero", false, Zero},
578		{"notZero", 42, NotZero},
579	}
580
581	for _, tt := range tests {
582		t.Run(tt.name, func(t *testing.T) {
583			tt.assertion(t, tt.value)
584		})
585	}
586}
587
588func ExampleBoolAssertionFunc() {
589	t := &testing.T{} // provided by test
590
591	isOkay := func(x int) bool {
592		return x >= 42
593	}
594
595	tests := []struct {
596		name      string
597		arg       int
598		assertion BoolAssertionFunc
599	}{
600		{"-1 is bad", -1, False},
601		{"42 is good", 42, True},
602		{"41 is bad", 41, False},
603		{"45 is cool", 45, True},
604	}
605
606	for _, tt := range tests {
607		t.Run(tt.name, func(t *testing.T) {
608			tt.assertion(t, isOkay(tt.arg))
609		})
610	}
611}
612
613func TestBoolAssertionFunc(t *testing.T) {
614	tests := []struct {
615		name      string
616		value     bool
617		assertion BoolAssertionFunc
618	}{
619		{"true", true, True},
620		{"false", false, False},
621	}
622
623	for _, tt := range tests {
624		t.Run(tt.name, func(t *testing.T) {
625			tt.assertion(t, tt.value)
626		})
627	}
628}
629
630func ExampleErrorAssertionFunc() {
631	t := &testing.T{} // provided by test
632
633	dumbParseNum := func(input string, v interface{}) error {
634		return json.Unmarshal([]byte(input), v)
635	}
636
637	tests := []struct {
638		name      string
639		arg       string
640		assertion ErrorAssertionFunc
641	}{
642		{"1.2 is number", "1.2", NoError},
643		{"1.2.3 not number", "1.2.3", Error},
644		{"true is not number", "true", Error},
645		{"3 is number", "3", NoError},
646	}
647
648	for _, tt := range tests {
649		t.Run(tt.name, func(t *testing.T) {
650			var x float64
651			tt.assertion(t, dumbParseNum(tt.arg, &x))
652		})
653	}
654}
655
656func TestErrorAssertionFunc(t *testing.T) {
657	tests := []struct {
658		name      string
659		err       error
660		assertion ErrorAssertionFunc
661	}{
662		{"noError", nil, NoError},
663		{"error", errors.New("whoops"), Error},
664	}
665
666	for _, tt := range tests {
667		t.Run(tt.name, func(t *testing.T) {
668			tt.assertion(t, tt.err)
669		})
670	}
671}
672