├── .gitignore ├── LICENSE ├── doc.go ├── README.md ├── decorate.go ├── is.go └── is_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 metabition 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Package is is a mini testing helper. 2 | // 3 | // func TestSomething(t *testing.T) { 4 | // is := is.New(t) 5 | // obj, err := MethodBeingTested() 6 | // is.OK(obj, err) // list of objects, all must be OK 7 | // is.Equal(obj, "Hello world") 8 | // } 9 | // 10 | // OK 11 | // 12 | // is.OK asserts that the specified object is OK, which means 13 | // different things for different types: 14 | // 15 | // bool - OK means not false 16 | // int - OK means not zero 17 | // error - OK means nil 18 | // string - OK means not "" 19 | // func() - OK means does not panic 20 | // everything else - OK means not nil 21 | // 22 | // Equality 23 | // 24 | // is.Equal asserts that two objects are effectively equal. 25 | // 26 | // Panics 27 | // 28 | // is.Panic and is.PanicWith asserts that the func() will panic. 29 | // PanicWith specifies the panic text that is expected: 30 | // 31 | // func TestInvalidArgs(t *testing.T) { 32 | // is := is.New(t) 33 | // is.Panic(func(){ 34 | // SomeMethod(1) 35 | // }) 36 | // is.PanicWith("invalid args, both cannot be nil", func(){ 37 | // OtherMethod(nil, nil) 38 | // }) 39 | // } 40 | // 41 | // Relaxed 42 | // 43 | // To prevent is from stopping when the first assertion fails, 44 | // you can use is.Relaxed(t), rather than is.New(t). 45 | // 46 | // func TestManyThings(t *testing.T) { 47 | // is := is.Relaxed(t) 48 | // thing, err := Something(); 49 | // is.OK(thing) 50 | // is.Nil(err) 51 | // another, err := Another(); 52 | // is.Nil(another) 53 | // is.Err(err) 54 | // // all assertions will be tried 55 | // } 56 | package is 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | is 2 | == 3 | 4 | [![GoDoc](https://godoc.org/github.com/cheekybits/is?status.png)](http://godoc.org/github.com/cheekybits/is) 5 | 6 | A mini testing helper for Go. 7 | 8 | * Simple interface (`is.OK` and `is.Equal`) 9 | * Plugs into existing Go toolchain (uses `testing.T`) 10 | * Obvious for newcomers and newbs 11 | * Also gives you `is.Panic` and `is.PanicWith` helpers - because testing panics is ugly 12 | 13 | ### Usage 14 | 15 | 1. Write test functions as usual 16 | 1. Add `is := is.New(t)` at top of your test functions 17 | 1. Call target code 18 | 1. Make assertions using new `is` object 19 | 20 | ``` 21 | func TestSomething(t *testing.T) { 22 | is := is.New(t) 23 | 24 | // ensure not nil 25 | obj := SomeFunc() 26 | is.OK(obj) 27 | 28 | // ensure no error 29 | obj, err := SomeFunc() 30 | is.NoErr(err) 31 | 32 | // ensure not false 33 | b := SomeBool() 34 | is.OK(b) 35 | 36 | // ensure not "" 37 | s := SomeString() 38 | is.OK(s) 39 | 40 | // ensure not zero 41 | is.OK(len(something)) 42 | 43 | // ensure doesn't panic 44 | is.OK(func(){ 45 | MethodShouldNotPanic() 46 | }) 47 | 48 | // ensure many things in one go 49 | is.OK(b, err, obj, "something") 50 | 51 | // ensure something does panic 52 | is.Panic(func(){ 53 | MethodShouldPanic(1) 54 | }) 55 | is.PanicWith("package: arg must be >0", func(){ 56 | MethodShouldPanicWithSpecificMessage(0) 57 | }) 58 | 59 | // make sure two values are equal 60 | is.Equal(1, 2) 61 | is.Equal(err, ErrSomething) 62 | is.Equal(a, b) 63 | 64 | } 65 | ``` 66 | 67 | ### Get started 68 | 69 | Get it: 70 | 71 | ``` 72 | go get github.com/cheekybits/is 73 | ``` 74 | 75 | Then import it: 76 | 77 | ``` 78 | import ( 79 | "testing" 80 | "github.com/cheekybits/is" 81 | ) 82 | ``` 83 | -------------------------------------------------------------------------------- /decorate.go: -------------------------------------------------------------------------------- 1 | package is 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "runtime" 7 | "strings" 8 | ) 9 | 10 | // callerinfo returns a string containing the file and line number of the test call 11 | // that failed. 12 | func callerinfo() (string, int, bool) { 13 | 14 | file := "" 15 | line := 0 16 | ok := false 17 | 18 | for i := 0; ; i++ { 19 | _, file, line, ok = runtime.Caller(i) 20 | if !ok { 21 | return "", 0, false 22 | } 23 | parts := strings.Split(file, "/") 24 | dir := parts[len(parts)-2] 25 | file = parts[len(parts)-1] 26 | if dir != "is" || file == "is_test.go" { 27 | break 28 | } 29 | } 30 | 31 | return file, line, ok 32 | } 33 | 34 | // decorate prefixes the string with the file and line of the call site 35 | // and inserts the final newline if needed and indentation tabs for formatting. 36 | // this function was copied from the testing framework. 37 | func decorate(s string) string { 38 | file, line, ok := callerinfo() // decorate + log + public function. 39 | if ok { 40 | // Truncate file name at last file name separator. 41 | if index := strings.LastIndex(file, "/"); index >= 0 { 42 | file = file[index+1:] 43 | } else if index = strings.LastIndex(file, "\\"); index >= 0 { 44 | file = file[index+1:] 45 | } 46 | } else { 47 | file = "???" 48 | line = 1 49 | } 50 | buf := new(bytes.Buffer) 51 | // Every line is indented at least one tab. 52 | buf.WriteByte('\t') 53 | fmt.Fprintf(buf, "%s:%d: ", file, line) 54 | lines := strings.Split(s, "\n") 55 | if l := len(lines); l > 1 && lines[l-1] == "" { 56 | lines = lines[:l-1] 57 | } 58 | for i, line := range lines { 59 | if i > 0 { 60 | // Second and subsequent lines are indented an extra tab. 61 | buf.WriteString("\n\t\t") 62 | } 63 | buf.WriteString(line) 64 | } 65 | buf.WriteByte('\n') 66 | return buf.String() 67 | } 68 | -------------------------------------------------------------------------------- /is.go: -------------------------------------------------------------------------------- 1 | package is 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "sync" 7 | ) 8 | 9 | // I represents the is interface. 10 | type I interface { 11 | // OK asserts that the specified objects are all OK. 12 | OK(o ...interface{}) 13 | // Equal asserts that the two values are 14 | // considered equal. Non strict. 15 | Equal(a, b interface{}) 16 | // NotEqual asserts that the two values are not 17 | // considered equal. Non strict. 18 | NotEqual(a, b interface{}) 19 | // NoErr asserts that the value is not an 20 | // error. 21 | NoErr(err ...error) 22 | // Err asserts that the value is an error. 23 | Err(err ...error) 24 | // Nil asserts that the specified objects are 25 | // all nil. 26 | Nil(obj ...interface{}) 27 | // NotNil asserts that the specified objects are 28 | // all nil. 29 | NotNil(obj ...interface{}) 30 | // True asserts that the specified objects are 31 | // all true 32 | True(obj ...interface{}) 33 | // False asserts that the specified objects are 34 | // all true 35 | False(obj ...interface{}) 36 | // Panic asserts that the specified function 37 | // panics. 38 | Panic(fn func()) 39 | // PanicWith asserts that the specified function 40 | // panics with the specific message. 41 | PanicWith(m string, fn func()) 42 | // Fail indicates that the test has failed with the 43 | // specified formatted arguments. 44 | Fail(args ...interface{}) 45 | // Failf indicates that the test has failed with the 46 | // formatted arguments. 47 | Failf(format string, args ...interface{}) 48 | } 49 | 50 | // New creates a new I capable of making 51 | // assertions. 52 | func New(t T) I { 53 | return &i{t: t} 54 | } 55 | 56 | // Relaxed creates a new I capable of making 57 | // assertions, but will not fail immediately 58 | // allowing all assertions to run. 59 | func Relaxed(t T) I { 60 | return &i{t: t, relaxed: true} 61 | } 62 | 63 | // T represents the an interface for reporting 64 | // failures. 65 | // testing.T satisfied this interface. 66 | type T interface { 67 | FailNow() 68 | } 69 | 70 | // i represents an implementation of interface I. 71 | type i struct { 72 | t T 73 | fails []string 74 | l sync.Mutex 75 | relaxed bool 76 | } 77 | 78 | func (i *i) Log(args ...interface{}) { 79 | i.l.Lock() 80 | fail := fmt.Sprint(args...) 81 | i.fails = append(i.fails, fail) 82 | fmt.Print(decorate(fail)) 83 | i.l.Unlock() 84 | if !i.relaxed { 85 | i.t.FailNow() 86 | } 87 | } 88 | func (i *i) Logf(format string, args ...interface{}) { 89 | i.l.Lock() 90 | fail := fmt.Sprintf(format, args...) 91 | i.fails = append(i.fails, fail) 92 | fmt.Print(decorate(fail)) 93 | i.l.Unlock() 94 | if !i.relaxed { 95 | i.t.FailNow() 96 | } 97 | } 98 | 99 | // OK asserts that the specified objects are all OK. 100 | func (i *i) OK(o ...interface{}) { 101 | for _, obj := range o { 102 | 103 | if isNil(obj) { 104 | i.Log("unexpected nil") 105 | } 106 | 107 | switch co := obj.(type) { 108 | case func(): 109 | // shouldn't panic 110 | var r interface{} 111 | func() { 112 | defer func() { 113 | r = recover() 114 | }() 115 | co() 116 | }() 117 | if r != nil { 118 | i.Logf("unexpected panic: %v", r) 119 | } 120 | return 121 | case string: 122 | if len(co) == 0 { 123 | i.Log("unexpected \"\"") 124 | } 125 | return 126 | case bool: 127 | // false 128 | if co == false { 129 | i.Log("unexpected false") 130 | return 131 | } 132 | } 133 | if isNil(o) { 134 | if _, ok := obj.(error); ok { 135 | // nil errors are ok 136 | return 137 | } 138 | i.Log("unexpected nil") 139 | return 140 | } 141 | 142 | if obj == 0 { 143 | i.Log("unexpected zero") 144 | } 145 | } 146 | } 147 | 148 | func (i *i) NoErr(errs ...error) { 149 | for n, err := range errs { 150 | if !isNil(err) { 151 | p := "unexpected error" 152 | if len(errs) > 1 { 153 | p += fmt.Sprintf(" (%d)", n) 154 | } 155 | p += ": " + err.Error() 156 | i.Logf(p) 157 | } 158 | } 159 | } 160 | 161 | func (i *i) Err(errs ...error) { 162 | for n, err := range errs { 163 | if isNil(err) { 164 | p := "error expected" 165 | if len(errs) > 1 { 166 | p += fmt.Sprintf(" (%d)", n) 167 | } 168 | i.Logf(p) 169 | } 170 | } 171 | } 172 | 173 | func (i *i) Nil(o ...interface{}) { 174 | for n, obj := range o { 175 | if !isNil(obj) { 176 | p := "expected nil" 177 | if len(o) > 1 { 178 | p += fmt.Sprintf(" (%d)", n) 179 | } 180 | p += ": " + fmt.Sprintf("%#v", obj) 181 | i.Logf(p) 182 | } 183 | } 184 | } 185 | 186 | func (i *i) NotNil(o ...interface{}) { 187 | for n, obj := range o { 188 | if isNil(obj) { 189 | p := "unexpected nil" 190 | if len(o) > 1 { 191 | p += fmt.Sprintf(" (%d)", n) 192 | } 193 | p += ": " + fmt.Sprintf("%#v", obj) 194 | i.Logf(p) 195 | } 196 | } 197 | } 198 | 199 | func (i *i) True(o ...interface{}) { 200 | for n, obj := range o { 201 | if b, ok := obj.(bool); !ok || b != true { 202 | p := "expected true" 203 | if len(o) > 1 { 204 | p += fmt.Sprintf(" (%d)", n) 205 | } 206 | p += ": " + fmt.Sprintf("%#v", obj) 207 | i.Logf(p) 208 | } 209 | } 210 | } 211 | 212 | func (i *i) False(o ...interface{}) { 213 | for n, obj := range o { 214 | if b, ok := obj.(bool); !ok || b != false { 215 | p := "expected false" 216 | if len(o) > 1 { 217 | p += fmt.Sprintf(" (%d)", n) 218 | } 219 | p += ": " + fmt.Sprintf("%#v", obj) 220 | i.Logf(p) 221 | } 222 | } 223 | } 224 | 225 | // Equal asserts that the two values are 226 | // considered equal. Non strict. 227 | func (i *i) Equal(a, b interface{}) { 228 | if !areEqual(a, b) { 229 | i.Logf("%v != %v", a, b) 230 | } 231 | } 232 | 233 | // NotEqual asserts that the two values are not 234 | // considered equal. Non strict. 235 | func (i *i) NotEqual(a, b interface{}) { 236 | if areEqual(a, b) { 237 | i.Logf("%v == %v", a, b) 238 | } 239 | } 240 | 241 | func (i *i) Fail(args ...interface{}) { 242 | i.Log(args...) 243 | } 244 | 245 | func (i *i) Failf(format string, args ...interface{}) { 246 | i.Logf(format, args...) 247 | } 248 | 249 | // Panic asserts that the specified function 250 | // panics. 251 | func (i *i) Panic(fn func()) { 252 | var r interface{} 253 | func() { 254 | defer func() { 255 | r = recover() 256 | }() 257 | fn() 258 | }() 259 | if r == nil { 260 | i.Log("expected panic") 261 | } 262 | } 263 | 264 | // PanicWith asserts that the specified function 265 | // panics with the specific message. 266 | func (i *i) PanicWith(m string, fn func()) { 267 | var r interface{} 268 | func() { 269 | defer func() { 270 | r = recover() 271 | }() 272 | fn() 273 | }() 274 | if r != m { 275 | i.Logf("expected panic: \"%s\"", m) 276 | } 277 | } 278 | 279 | // isNil gets whether the object is nil or not. 280 | func isNil(object interface{}) bool { 281 | if object == nil { 282 | return true 283 | } 284 | value := reflect.ValueOf(object) 285 | kind := value.Kind() 286 | if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { 287 | return true 288 | } 289 | return false 290 | } 291 | 292 | // areEqual gets whether a equals b or not. 293 | func areEqual(a, b interface{}) bool { 294 | if isNil(a) || isNil(b) { 295 | if isNil(a) && !isNil(b) { 296 | return false 297 | } 298 | if !isNil(a) && isNil(b) { 299 | return false 300 | } 301 | return a == b 302 | } 303 | if reflect.DeepEqual(a, b) { 304 | return true 305 | } 306 | aValue := reflect.ValueOf(a) 307 | bValue := reflect.ValueOf(b) 308 | if aValue == bValue { 309 | return true 310 | } 311 | 312 | // Attempt comparison after type conversion 313 | if bValue.Type().ConvertibleTo(aValue.Type()) { 314 | return reflect.DeepEqual(a, bValue.Convert(aValue.Type()).Interface()) 315 | } 316 | // Last ditch effort 317 | if fmt.Sprintf("%#v", a) == fmt.Sprintf("%#v", b) { 318 | return true 319 | } 320 | 321 | return false 322 | } 323 | -------------------------------------------------------------------------------- /is_test.go: -------------------------------------------------------------------------------- 1 | package is 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | type customErr struct{} 10 | 11 | func (e *customErr) Error() string { 12 | return "Oops" 13 | } 14 | 15 | type mockT struct { 16 | failed bool 17 | } 18 | 19 | func (m *mockT) FailNow() { 20 | m.failed = true 21 | } 22 | func (m *mockT) Failed() bool { 23 | return m.failed 24 | } 25 | 26 | func TestIs(t *testing.T) { 27 | 28 | for _, test := range []struct { 29 | N string 30 | F func(is I) 31 | Fails []string 32 | }{ 33 | { 34 | N: "Fail('msg')", 35 | F: func(is I) { 36 | is.Fail("something") 37 | }, 38 | Fails: []string{"failed: something"}, 39 | }, 40 | { 41 | N: "Failf('%d is wrong',123)", 42 | F: func(is I) { 43 | is.Failf("%d is wrong", 123) 44 | }, 45 | Fails: []string{"failed: 123 is wrong"}, 46 | }, 47 | // is.Nil 48 | { 49 | N: "Nil(nil)", 50 | F: func(is I) { 51 | is.Nil(nil) 52 | }, 53 | }, 54 | { 55 | N: "Nil(\"nope\")", 56 | F: func(is I) { 57 | is.Nil("nope") 58 | }, 59 | Fails: []string{"expected nil: \"nope\""}, 60 | }, 61 | // is.NotNil 62 | { 63 | N: "NotNil(\"nope\")", 64 | F: func(is I) { 65 | is.NotNil("nope") 66 | }, 67 | }, 68 | { 69 | N: "NotNil(nil)", 70 | F: func(is I) { 71 | is.NotNil(nil) 72 | }, 73 | Fails: []string{"unexpected nil"}, 74 | }, 75 | // is.OK 76 | { 77 | N: "OK(false)", 78 | F: func(is I) { 79 | is.OK(false) 80 | }, 81 | Fails: []string{"unexpected false"}, 82 | }, { 83 | N: "OK(true)", 84 | F: func(is I) { 85 | is.OK(true) 86 | }, 87 | }, { 88 | N: "OK(nil)", 89 | F: func(is I) { 90 | is.OK(nil) 91 | }, 92 | Fails: []string{"unexpected nil"}, 93 | }, { 94 | N: "OK(1,2,3)", 95 | F: func(is I) { 96 | is.OK(1, 2, 3) 97 | }, 98 | }, { 99 | N: "OK(0)", 100 | F: func(is I) { 101 | is.OK(0) 102 | }, 103 | Fails: []string{"unexpected zero"}, 104 | }, { 105 | N: "OK(1)", 106 | F: func(is I) { 107 | is.OK(1) 108 | }, 109 | }, { 110 | N: "OK(\"\")", 111 | F: func(is I) { 112 | is.OK("") 113 | }, 114 | Fails: []string{"unexpected \"\""}, 115 | }, 116 | // NoErr 117 | { 118 | N: "NoErr(errors.New(\"an error\"))", 119 | F: func(is I) { 120 | is.NoErr(errors.New("an error")) 121 | }, 122 | Fails: []string{"unexpected error: an error"}, 123 | }, { 124 | N: "NoErr(&customErr{})", 125 | F: func(is I) { 126 | is.NoErr(&customErr{}) 127 | }, 128 | Fails: []string{"unexpected error: Oops"}, 129 | }, { 130 | N: "NoErr(error(nil))", 131 | F: func(is I) { 132 | var err error 133 | is.NoErr(err) 134 | }, 135 | }, 136 | { 137 | N: "NoErr(err1, err2, err3)", 138 | F: func(is I) { 139 | is.NoErr(&customErr{}, &customErr{}, &customErr{}) 140 | }, 141 | Fails: []string{"unexpected error: Oops"}, 142 | }, 143 | { 144 | N: "NoErr(err1, err2, err3)", 145 | F: func(is I) { 146 | var err1 error 147 | var err2 error 148 | var err3 error 149 | is.NoErr(err1, err2, err3) 150 | }, 151 | }, 152 | // Err 153 | { 154 | N: "Err(errors.New(\"an error\"))", 155 | F: func(is I) { 156 | is.Err(errors.New("an error")) 157 | }, 158 | }, { 159 | N: "Err(&customErr{})", 160 | F: func(is I) { 161 | is.Err(&customErr{}) 162 | }, 163 | }, { 164 | N: "Err(error(nil))", 165 | F: func(is I) { 166 | var err error 167 | is.Err(err) 168 | }, 169 | Fails: []string{"error expected"}, 170 | }, 171 | { 172 | N: "Err(customErr1, customErr2, customErr3)", 173 | F: func(is I) { 174 | is.Err(&customErr{}, &customErr{}, &customErr{}) 175 | }, 176 | }, 177 | { 178 | N: "Err(err1, err2, err3)", 179 | F: func(is I) { 180 | var err1 error 181 | var err2 error 182 | var err3 error 183 | is.Err(err1, err2, err3) 184 | }, 185 | Fails: []string{"error expected"}, 186 | }, 187 | // OK 188 | { 189 | N: "OK(customErr(nil))", 190 | F: func(is I) { 191 | var err *customErr 192 | is.NoErr(err) 193 | }, 194 | }, { 195 | N: "OK(func) panic", 196 | F: func(is I) { 197 | is.OK(func() { 198 | panic("panic message") 199 | }) 200 | }, 201 | Fails: []string{"unexpected panic: panic message"}, 202 | }, { 203 | N: "OK(func) no panic", 204 | F: func(is I) { 205 | is.OK(func() {}) 206 | }, 207 | }, 208 | // is.Panic 209 | { 210 | N: "PanicWith(\"panic message\", func(){ panic() })", 211 | F: func(is I) { 212 | is.PanicWith("panic message", func() { 213 | panic("panic message") 214 | }) 215 | }, 216 | }, 217 | { 218 | N: "PanicWith(\"panic message\", func(){ /* no panic */ })", 219 | F: func(is I) { 220 | is.PanicWith("panic message", func() { 221 | }) 222 | }, 223 | Fails: []string{"expected panic: \"panic message\""}, 224 | }, 225 | { 226 | N: "Panic(func(){ panic() })", 227 | F: func(is I) { 228 | is.Panic(func() { 229 | panic("panic message") 230 | }) 231 | }, 232 | }, 233 | { 234 | N: "Panic(func(){ /* no panic */ })", 235 | F: func(is I) { 236 | is.Panic(func() { 237 | }) 238 | }, 239 | Fails: []string{"expected panic"}, 240 | }, 241 | // is.Equal 242 | { 243 | N: "Equal(msi,msi) nil maps", 244 | F: func(is I) { 245 | var m1 map[string]interface{} 246 | var m2 map[string]interface{} 247 | is.Equal(m1, m2) 248 | }, 249 | }, 250 | { 251 | N: "Equal(1,1)", 252 | F: func(is I) { 253 | is.Equal(1, 1) 254 | }, 255 | }, { 256 | N: "Equal(1,2)", 257 | F: func(is I) { 258 | is.Equal(1, 2) 259 | }, 260 | Fails: []string{"1 != 2"}, 261 | }, { 262 | N: "Equal(1,nil)", 263 | F: func(is I) { 264 | is.Equal(1, nil) 265 | }, 266 | Fails: []string{"1 != "}, 267 | }, { 268 | N: "Equal(nil,1)", 269 | F: func(is I) { 270 | is.Equal(nil, 1) 271 | }, 272 | Fails: []string{" != 1"}, 273 | }, 274 | { 275 | N: "Equal(uint64(1),int64(1))", 276 | F: func(is I) { 277 | is.Equal(uint64(1), int64(1)) 278 | }, 279 | }, 280 | { 281 | N: "Equal(false,false)", 282 | F: func(is I) { 283 | is.Equal(false, false) 284 | }, 285 | }, { 286 | N: "Equal(map1,map2)", 287 | F: func(is I) { 288 | is.Equal( 289 | map[string]interface{}{"package": "is"}, 290 | map[string]interface{}{"package": "is"}, 291 | ) 292 | }, 293 | }, 294 | 295 | // is.True 296 | { 297 | N: "True(true,true)", 298 | F: func(is I) { 299 | is.True(true, true) 300 | }, 301 | }, { 302 | N: "True(false,false)", 303 | F: func(is I) { 304 | is.True(false, false) 305 | }, 306 | Fails: []string{"true!=false"}, 307 | }, 308 | // is.False 309 | { 310 | N: "False(false,false)", 311 | F: func(is I) { 312 | is.False(false, false) 313 | }, 314 | }, { 315 | N: "False(true,true)", 316 | F: func(is I) { 317 | is.False(true, true) 318 | }, 319 | Fails: []string{"false!=true"}, 320 | }, 321 | 322 | // is.NotEqual 323 | { 324 | N: "NotEqual(1,2)", 325 | F: func(is I) { 326 | is.NotEqual(1, 2) 327 | }, 328 | }, { 329 | N: "NotEqual(1,1)", 330 | F: func(is I) { 331 | is.NotEqual(1, 1) 332 | }, 333 | Fails: []string{"1 == 1"}, 334 | }, { 335 | N: "NotEqual(1,nil)", 336 | F: func(is I) { 337 | is.NotEqual(1, nil) 338 | }, 339 | }, { 340 | N: "NotEqual(nil,1)", 341 | F: func(is I) { 342 | is.NotEqual(nil, 1) 343 | }, 344 | }, { 345 | N: "NotEqual(false,false)", 346 | F: func(is I) { 347 | is.NotEqual(false, false) 348 | }, 349 | Fails: []string{"false == false"}, 350 | }, { 351 | N: "NotEqual(map1,map2)", 352 | F: func(is I) { 353 | is.NotEqual( 354 | map[string]interface{}{"package": "is"}, 355 | map[string]interface{}{"package": "isn't"}, 356 | ) 357 | }, 358 | }} { 359 | 360 | tt := new(mockT) 361 | is := New(tt) 362 | 363 | func() { 364 | defer func() { 365 | recover() 366 | }() 367 | test.F(is) 368 | }() 369 | 370 | if len(test.Fails) > 0 { 371 | for n, fail := range test.Fails { 372 | if !tt.Failed() { 373 | t.Errorf("%s should fail", test.N) 374 | } 375 | if test.Fails[n] != fail { 376 | t.Errorf("expected fail \"%s\" but was \"%s\".", test.Fails[n], fail) 377 | } 378 | } 379 | } else { 380 | if tt.Failed() { 381 | t.Errorf("%s shouldn't fail but: %s", test.N, strings.Join(test.Fails, ", ")) 382 | } 383 | } 384 | 385 | } 386 | 387 | } 388 | 389 | func TestNewStrict(t *testing.T) { 390 | tt := new(mockT) 391 | is := Relaxed(tt) 392 | 393 | is.OK(nil) 394 | is.Equal(1, 2) 395 | is.NoErr(errors.New("nope")) 396 | 397 | if tt.Failed() { 398 | t.Error("Relaxed should not call FailNow") 399 | } 400 | 401 | } 402 | --------------------------------------------------------------------------------