github.com/zhongdalu/gf@v1.0.0/g/test/gtest/gtest.go (about) 1 // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 // Package gtest provides convenient test utilities for unit testing. 8 package gtest 9 10 import ( 11 "fmt" 12 "os" 13 "reflect" 14 "testing" 15 16 "github.com/zhongdalu/gf/g/internal/debug" 17 18 "github.com/zhongdalu/gf/g/util/gconv" 19 ) 20 21 const ( 22 gPATH_FILTER_KEY = "/g/test/gtest/gtest" 23 ) 24 25 // Case creates an unit test case. 26 // The parameter <t> is the pointer to testing.T of stdlib (*testing.T). 27 // The parameter <f> is the callback function for unit test case. 28 func Case(t *testing.T, f func()) { 29 defer func() { 30 if err := recover(); err != nil { 31 fmt.Fprintf(os.Stderr, "%v\n%s", err, debug.StackWithFilter(gPATH_FILTER_KEY)) 32 t.Fail() 33 } 34 }() 35 f() 36 } 37 38 // Assert checks <value> and <expect> EQUAL. 39 func Assert(value, expect interface{}) { 40 rvExpect := reflect.ValueOf(expect) 41 if isNil(value) { 42 value = nil 43 } 44 if rvExpect.Kind() == reflect.Map { 45 if err := compareMap(value, expect); err != nil { 46 panic(err) 47 } 48 return 49 } 50 strValue := gconv.String(value) 51 strExpect := gconv.String(expect) 52 if strValue != strExpect { 53 panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, strValue, strExpect)) 54 } 55 } 56 57 // AssertEQ checks <value> and <expect> EQUAL, including their TYPES. 58 func AssertEQ(value, expect interface{}) { 59 // Value assert. 60 rvExpect := reflect.ValueOf(expect) 61 if isNil(value) { 62 value = nil 63 } 64 if rvExpect.Kind() == reflect.Map { 65 if err := compareMap(value, expect); err != nil { 66 panic(err) 67 } 68 return 69 } 70 strValue := gconv.String(value) 71 strExpect := gconv.String(expect) 72 if strValue != strExpect { 73 panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, strValue, strExpect)) 74 } 75 // Type assert. 76 t1 := reflect.TypeOf(value) 77 t2 := reflect.TypeOf(expect) 78 if t1 != t2 { 79 panic(fmt.Sprintf(`[ASSERT] EXPECT TYPE %v[%v] == %v[%v]`, strValue, t1, strExpect, t2)) 80 } 81 } 82 83 // AssertNE checks <value> and <expect> NOT EQUAL. 84 func AssertNE(value, expect interface{}) { 85 rvExpect := reflect.ValueOf(expect) 86 if isNil(value) { 87 value = nil 88 } 89 if rvExpect.Kind() == reflect.Map { 90 if err := compareMap(value, expect); err == nil { 91 panic(fmt.Sprintf(`[ASSERT] EXPECT %v != %v`, value, expect)) 92 } 93 return 94 } 95 strValue := gconv.String(value) 96 strExpect := gconv.String(expect) 97 if strValue == strExpect { 98 panic(fmt.Sprintf(`[ASSERT] EXPECT %v != %v`, strValue, strExpect)) 99 } 100 } 101 102 // AssertGT checks <value> is GREATER THAN <expect>. 103 // Notice that, only string, integer and float types can be compared by AssertGT, 104 // others are invalid. 105 func AssertGT(value, expect interface{}) { 106 passed := false 107 switch reflect.ValueOf(expect).Kind() { 108 case reflect.String: 109 passed = gconv.String(value) > gconv.String(expect) 110 111 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 112 passed = gconv.Int(value) > gconv.Int(expect) 113 114 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 115 passed = gconv.Uint(value) > gconv.Uint(expect) 116 117 case reflect.Float32, reflect.Float64: 118 passed = gconv.Float64(value) > gconv.Float64(expect) 119 } 120 if !passed { 121 panic(fmt.Sprintf(`[ASSERT] EXPECT %v > %v`, value, expect)) 122 } 123 } 124 125 // Deprecated. 126 // See AssertGE. 127 func AssertGTE(value, expect interface{}) { 128 AssertGE(value, expect) 129 } 130 131 // AssertGE checks <value> is GREATER OR EQUAL THAN <expect>. 132 // Notice that, only string, integer and float types can be compared by AssertGTE, 133 // others are invalid. 134 func AssertGE(value, expect interface{}) { 135 passed := false 136 switch reflect.ValueOf(expect).Kind() { 137 case reflect.String: 138 passed = gconv.String(value) >= gconv.String(expect) 139 140 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 141 passed = gconv.Int(value) >= gconv.Int(expect) 142 143 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 144 passed = gconv.Uint(value) >= gconv.Uint(expect) 145 146 case reflect.Float32, reflect.Float64: 147 passed = gconv.Float64(value) >= gconv.Float64(expect) 148 } 149 if !passed { 150 panic(fmt.Sprintf(`[ASSERT] EXPECT %v >= %v`, value, expect)) 151 } 152 } 153 154 // AssertLT checks <value> is LESS EQUAL THAN <expect>. 155 // Notice that, only string, integer and float types can be compared by AssertLT, 156 // others are invalid. 157 func AssertLT(value, expect interface{}) { 158 passed := false 159 switch reflect.ValueOf(expect).Kind() { 160 case reflect.String: 161 passed = gconv.String(value) < gconv.String(expect) 162 163 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 164 passed = gconv.Int(value) < gconv.Int(expect) 165 166 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 167 passed = gconv.Uint(value) < gconv.Uint(expect) 168 169 case reflect.Float32, reflect.Float64: 170 passed = gconv.Float64(value) < gconv.Float64(expect) 171 } 172 if !passed { 173 panic(fmt.Sprintf(`[ASSERT] EXPECT %v < %v`, value, expect)) 174 } 175 } 176 177 // Deprecated. 178 // See AssertLE. 179 func AssertLTE(value, expect interface{}) { 180 AssertLE(value, expect) 181 } 182 183 // AssertLE checks <value> is LESS OR EQUAL THAN <expect>. 184 // Notice that, only string, integer and float types can be compared by AssertLTE, 185 // others are invalid. 186 func AssertLE(value, expect interface{}) { 187 passed := false 188 switch reflect.ValueOf(expect).Kind() { 189 case reflect.String: 190 passed = gconv.String(value) <= gconv.String(expect) 191 192 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 193 passed = gconv.Int(value) <= gconv.Int(expect) 194 195 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 196 passed = gconv.Uint(value) <= gconv.Uint(expect) 197 198 case reflect.Float32, reflect.Float64: 199 passed = gconv.Float64(value) <= gconv.Float64(expect) 200 } 201 if !passed { 202 panic(fmt.Sprintf(`[ASSERT] EXPECT %v <= %v`, value, expect)) 203 } 204 } 205 206 // AssertIN checks <value> is IN <expect>. 207 // The <expect> should be a slice, 208 // but the <value> can be a slice or a basic type variable. 209 // TODO map support. 210 func AssertIN(value, expect interface{}) { 211 passed := true 212 switch reflect.ValueOf(expect).Kind() { 213 case reflect.Slice, reflect.Array: 214 expectSlice := gconv.Interfaces(expect) 215 for _, v1 := range gconv.Interfaces(value) { 216 result := false 217 for _, v2 := range expectSlice { 218 if v1 == v2 { 219 result = true 220 break 221 } 222 } 223 if !result { 224 passed = false 225 break 226 } 227 } 228 } 229 if !passed { 230 panic(fmt.Sprintf(`[ASSERT] EXPECT %v IN %v`, value, expect)) 231 } 232 } 233 234 // AssertNI checks <value> is NOT IN <expect>. 235 // The <expect> should be a slice, 236 // but the <value> can be a slice or a basic type variable. 237 // TODO map support. 238 func AssertNI(value, expect interface{}) { 239 passed := true 240 switch reflect.ValueOf(expect).Kind() { 241 case reflect.Slice, reflect.Array: 242 for _, v1 := range gconv.Interfaces(value) { 243 result := true 244 for _, v2 := range gconv.Interfaces(expect) { 245 if v1 == v2 { 246 result = false 247 break 248 } 249 } 250 if !result { 251 passed = false 252 break 253 } 254 } 255 } 256 if !passed { 257 panic(fmt.Sprintf(`[ASSERT] EXPECT %v NOT IN %v`, value, expect)) 258 } 259 } 260 261 // Error panics with given <message>. 262 func Error(message ...interface{}) { 263 panic(fmt.Sprintf("[ERROR] %s", fmt.Sprint(message...))) 264 } 265 266 // Fatal prints <message> to stderr and exit the process. 267 func Fatal(message ...interface{}) { 268 fmt.Fprintf(os.Stderr, "[FATAL] %s\n%s", fmt.Sprint(message...), debug.StackWithFilter(gPATH_FILTER_KEY)) 269 os.Exit(1) 270 } 271 272 // compareMap compares two maps, returns nil if they are equal, or else returns error. 273 func compareMap(value, expect interface{}) error { 274 rvValue := reflect.ValueOf(value) 275 rvExpect := reflect.ValueOf(expect) 276 if isNil(value) { 277 value = nil 278 } 279 if rvExpect.Kind() == reflect.Map { 280 if rvValue.Kind() == reflect.Map { 281 if rvExpect.Len() == rvValue.Len() { 282 // Turn two interface maps to the same type for comparison. 283 // Direct use of rvValue.MapIndex(key).Interface() will panic 284 // when the key types are inconsistent. 285 mValue := make(map[string]string) 286 mExpect := make(map[string]string) 287 ksValue := rvValue.MapKeys() 288 ksExpect := rvExpect.MapKeys() 289 for _, key := range ksValue { 290 mValue[gconv.String(key.Interface())] = gconv.String(rvValue.MapIndex(key).Interface()) 291 } 292 for _, key := range ksExpect { 293 mExpect[gconv.String(key.Interface())] = gconv.String(rvExpect.MapIndex(key).Interface()) 294 } 295 for k, v := range mExpect { 296 if v != mValue[k] { 297 return fmt.Errorf(`[ASSERT] EXPECT VALUE map["%v"]:%v == map["%v"]:%v`+ 298 "\nGIVEN : %v\nEXPECT: %v", k, mValue[k], k, v, mValue, mExpect) 299 } 300 } 301 } else { 302 return fmt.Errorf(`[ASSERT] EXPECT MAP LENGTH %d == %d`, rvValue.Len(), rvExpect.Len()) 303 } 304 } else { 305 return fmt.Errorf(`[ASSERT] EXPECT VALUE TO BE A MAP`) 306 } 307 } 308 return nil 309 } 310 311 // isNil checks whether <value> is nil. 312 func isNil(value interface{}) bool { 313 rv := reflect.ValueOf(value) 314 switch rv.Kind() { 315 case reflect.Slice, reflect.Array, reflect.Map, reflect.Ptr, reflect.Func: 316 return rv.IsNil() 317 default: 318 return value == nil 319 } 320 }