package require import ( "encoding/json" "errors" "testing" "time" ) // AssertionTesterInterface defines an interface to be used for testing assertion methods type AssertionTesterInterface interface { TestMethod() } // AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface type AssertionTesterConformingObject struct { } func (a *AssertionTesterConformingObject) TestMethod() { } // AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface type AssertionTesterNonConformingObject struct { } type MockT struct { Failed bool } func (t *MockT) FailNow() { t.Failed = true } func (t *MockT) Errorf(format string, args ...interface{}) { _, _ = format, args } func TestImplements(t *testing.T) { Implements(t, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) mockT := new(MockT) Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestIsType(t *testing.T) { IsType(t, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) mockT := new(MockT) IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestEqual(t *testing.T) { Equal(t, 1, 1) mockT := new(MockT) Equal(mockT, 1, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestNotEqual(t *testing.T) { NotEqual(t, 1, 2) mockT := new(MockT) NotEqual(mockT, 2, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestExactly(t *testing.T) { a := float32(1) b := float32(1) c := float64(1) Exactly(t, a, b) mockT := new(MockT) Exactly(mockT, a, c) if !mockT.Failed { t.Error("Check should fail") } } func TestNotNil(t *testing.T) { NotNil(t, new(AssertionTesterConformingObject)) mockT := new(MockT) NotNil(mockT, nil) if !mockT.Failed { t.Error("Check should fail") } } func TestNil(t *testing.T) { Nil(t, nil) mockT := new(MockT) Nil(mockT, new(AssertionTesterConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestTrue(t *testing.T) { True(t, true) mockT := new(MockT) True(mockT, false) if !mockT.Failed { t.Error("Check should fail") } } func TestFalse(t *testing.T) { False(t, false) mockT := new(MockT) False(mockT, true) if !mockT.Failed { t.Error("Check should fail") } } func TestContains(t *testing.T) { Contains(t, "Hello World", "Hello") mockT := new(MockT) Contains(mockT, "Hello World", "Salut") if !mockT.Failed { t.Error("Check should fail") } } func TestNotContains(t *testing.T) { NotContains(t, "Hello World", "Hello!") mockT := new(MockT) NotContains(mockT, "Hello World", "Hello") if !mockT.Failed { t.Error("Check should fail") } } func TestPanics(t *testing.T) { Panics(t, func() { panic("Panic!") }) mockT := new(MockT) Panics(mockT, func() {}) if !mockT.Failed { t.Error("Check should fail") } } func TestNotPanics(t *testing.T) { NotPanics(t, func() {}) mockT := new(MockT) NotPanics(mockT, func() { panic("Panic!") }) if !mockT.Failed { t.Error("Check should fail") } } func TestNoError(t *testing.T) { NoError(t, nil) mockT := new(MockT) NoError(mockT, errors.New("some error")) if !mockT.Failed { t.Error("Check should fail") } } func TestError(t *testing.T) { Error(t, errors.New("some error")) mockT := new(MockT) Error(mockT, nil) if !mockT.Failed { t.Error("Check should fail") } } func TestEqualError(t *testing.T) { EqualError(t, errors.New("some error"), "some error") mockT := new(MockT) EqualError(mockT, errors.New("some error"), "Not some error") if !mockT.Failed { t.Error("Check should fail") } } func TestEmpty(t *testing.T) { Empty(t, "") mockT := new(MockT) Empty(mockT, "x") if !mockT.Failed { t.Error("Check should fail") } } func TestNotEmpty(t *testing.T) { NotEmpty(t, "x") mockT := new(MockT) NotEmpty(mockT, "") if !mockT.Failed { t.Error("Check should fail") } } func TestWithinDuration(t *testing.T) { a := time.Now() b := a.Add(10 * time.Second) WithinDuration(t, a, b, 15*time.Second) mockT := new(MockT) WithinDuration(mockT, a, b, 5*time.Second) if !mockT.Failed { t.Error("Check should fail") } } func TestInDelta(t *testing.T) { InDelta(t, 1.001, 1, 0.01) mockT := new(MockT) InDelta(mockT, 1, 2, 0.5) if !mockT.Failed { t.Error("Check should fail") } } func TestZero(t *testing.T) { Zero(t, "") mockT := new(MockT) Zero(mockT, "x") if !mockT.Failed { t.Error("Check should fail") } } func TestNotZero(t *testing.T) { NotZero(t, "x") mockT := new(MockT) NotZero(mockT, "") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_EqualSONString(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_EquivalentButNotEqual(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_HashOfArraysAndHashes(t *testing.T) { mockT := new(MockT) 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}", "{\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}") if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_Array(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_HashesNotEquivalent(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ActualIsNotJSON(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"foo": "bar"}`, "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ExpectedIsNotJSON(t *testing.T) { mockT := new(MockT) JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) { mockT := new(MockT) JSONEq(mockT, "Not JSON", "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) if !mockT.Failed { t.Error("Check should fail") } } func ExampleComparisonAssertionFunc() { t := &testing.T{} // provided by test adder := func(x, y int) int { return x + y } type args struct { x int y int } tests := []struct { name string args args expect int assertion ComparisonAssertionFunc }{ {"2+2=4", args{2, 2}, 4, Equal}, {"2+2!=5", args{2, 2}, 5, NotEqual}, {"2+3==5", args{2, 3}, 5, Exactly}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y)) }) } } func TestComparisonAssertionFunc(t *testing.T) { type iface interface { Name() string } tests := []struct { name string expect interface{} got interface{} assertion ComparisonAssertionFunc }{ {"implements", (*iface)(nil), t, Implements}, {"isType", (*testing.T)(nil), t, IsType}, {"equal", t, t, Equal}, {"equalValues", t, t, EqualValues}, {"exactly", t, t, Exactly}, {"notEqual", t, nil, NotEqual}, {"notContains", []int{1, 2, 3}, 4, NotContains}, {"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset}, {"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset}, {"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch}, {"regexp", "^t.*y$", "testify", Regexp}, {"notRegexp", "^t.*y$", "Testify", NotRegexp}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.expect, tt.got) }) } } func ExampleValueAssertionFunc() { t := &testing.T{} // provided by test dumbParse := func(input string) interface{} { var x interface{} json.Unmarshal([]byte(input), &x) return x } tests := []struct { name string arg string assertion ValueAssertionFunc }{ {"true is not nil", "true", NotNil}, {"empty string is nil", "", Nil}, {"zero is not nil", "0", NotNil}, {"zero is zero", "0", Zero}, {"false is zero", "false", Zero}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, dumbParse(tt.arg)) }) } } func TestValueAssertionFunc(t *testing.T) { tests := []struct { name string value interface{} assertion ValueAssertionFunc }{ {"notNil", true, NotNil}, {"nil", nil, Nil}, {"empty", []int{}, Empty}, {"notEmpty", []int{1}, NotEmpty}, {"zero", false, Zero}, {"notZero", 42, NotZero}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.value) }) } } func ExampleBoolAssertionFunc() { t := &testing.T{} // provided by test isOkay := func(x int) bool { return x >= 42 } tests := []struct { name string arg int assertion BoolAssertionFunc }{ {"-1 is bad", -1, False}, {"42 is good", 42, True}, {"41 is bad", 41, False}, {"45 is cool", 45, True}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, isOkay(tt.arg)) }) } } func TestBoolAssertionFunc(t *testing.T) { tests := []struct { name string value bool assertion BoolAssertionFunc }{ {"true", true, True}, {"false", false, False}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.value) }) } } func ExampleErrorAssertionFunc() { t := &testing.T{} // provided by test dumbParseNum := func(input string, v interface{}) error { return json.Unmarshal([]byte(input), v) } tests := []struct { name string arg string assertion ErrorAssertionFunc }{ {"1.2 is number", "1.2", NoError}, {"1.2.3 not number", "1.2.3", Error}, {"true is not number", "true", Error}, {"3 is number", "3", NoError}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var x float64 tt.assertion(t, dumbParseNum(tt.arg, &x)) }) } } func TestErrorAssertionFunc(t *testing.T) { tests := []struct { name string err error assertion ErrorAssertionFunc }{ {"noError", nil, NoError}, {"error", errors.New("whoops"), Error}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.err) }) } }