1 /* 2 Package assert provides assertions for comparing expected values to actual 3 values in tests. When an assertion fails a helpful error message is printed. 4 5 # Example usage 6 7 All the assertions in this package use [testing.T.Helper] to mark themselves as 8 test helpers. This allows the testing package to print the filename and line 9 number of the file function that failed. 10 11 assert.NilError(t, err) 12 // filename_test.go:212: assertion failed: error is not nil: file not found 13 14 If any assertion is called from a helper function, make sure to call t.Helper 15 from the helper function so that the filename and line number remain correct. 16 17 The examples below show assert used with some common types and the failure 18 messages it produces. The filename and line number portion of the failure 19 message is omitted from these examples for brevity. 20 21 // booleans 22 23 assert.Assert(t, ok) 24 // assertion failed: ok is false 25 assert.Assert(t, !missing) 26 // assertion failed: missing is true 27 28 // primitives 29 30 assert.Equal(t, count, 1) 31 // assertion failed: 0 (count int) != 1 (int) 32 assert.Equal(t, msg, "the message") 33 // assertion failed: my message (msg string) != the message (string) 34 assert.Assert(t, total != 10) // use Assert for NotEqual 35 // assertion failed: total is 10 36 assert.Assert(t, count > 20, "count=%v", count) 37 // assertion failed: count is <= 20: count=1 38 39 // errors 40 41 assert.NilError(t, closer.Close()) 42 // assertion failed: error is not nil: close /file: errno 11 43 assert.Error(t, err, "the exact error message") 44 // assertion failed: expected error "the exact error message", got "oops" 45 assert.ErrorContains(t, err, "includes this") 46 // assertion failed: expected error to contain "includes this", got "oops" 47 assert.ErrorIs(t, err, os.ErrNotExist) 48 // assertion failed: error is "oops", not "file does not exist" (os.ErrNotExist) 49 50 // complex types 51 52 assert.DeepEqual(t, result, myStruct{Name: "title"}) 53 // assertion failed: ... (diff of the two structs) 54 assert.Assert(t, is.Len(items, 3)) 55 // assertion failed: expected [] (length 0) to have length 3 56 assert.Assert(t, len(sequence) != 0) // use Assert for NotEmpty 57 // assertion failed: len(sequence) is 0 58 assert.Assert(t, is.Contains(mapping, "key")) 59 // assertion failed: map[other:1] does not contain key 60 61 // pointers and interface 62 63 assert.Assert(t, ref == nil) 64 // assertion failed: ref is not nil 65 assert.Assert(t, ref != nil) // use Assert for NotNil 66 // assertion failed: ref is nil 67 68 # Assert and Check 69 70 [Assert] and [Check] are very similar, they both accept a [cmp.Comparison], and fail 71 the test when the comparison fails. The one difference is that Assert uses 72 [testing.T.FailNow] to fail the test, which will end the test execution immediately. 73 Check uses [testing.T.Fail] to fail the test, which allows it to return the 74 result of the comparison, then proceed with the rest of the test case. 75 76 Like [testing.T.FailNow], [Assert] must be called from the goroutine running the test, 77 not from other goroutines created during the test. [Check] is safe to use from any 78 goroutine. 79 80 # Comparisons 81 82 Package [gotest.tools/v3/assert/cmp] provides 83 many common comparisons. Additional comparisons can be written to compare 84 values in other ways. See the example Assert (CustomComparison). 85 86 # Automated migration from testify 87 88 gty-migrate-from-testify is a command which translates Go source code from 89 testify assertions to the assertions provided by this package. 90 91 See http://pkg.go.dev/gotest.tools/v3/assert/cmd/gty-migrate-from-testify. 92 */ 93 package assert // import "gotest.tools/v3/assert" 94 95 import ( 96 gocmp "github.com/google/go-cmp/cmp" 97 "gotest.tools/v3/assert/cmp" 98 "gotest.tools/v3/internal/assert" 99 ) 100 101 // BoolOrComparison can be a bool, [cmp.Comparison], or error. See [Assert] for 102 // details about how this type is used. 103 type BoolOrComparison interface{} 104 105 // TestingT is the subset of [testing.T] (see also [testing.TB]) used by the assert package. 106 type TestingT interface { 107 FailNow() 108 Fail() 109 Log(args ...interface{}) 110 } 111 112 type helperT interface { 113 Helper() 114 } 115 116 // Assert performs a comparison. If the comparison fails, the test is marked as 117 // failed, a failure message is logged, and execution is stopped immediately. 118 // 119 // The comparison argument may be one of three types: 120 // 121 // bool 122 // True is success. False is a failure. The failure message will contain 123 // the literal source code of the expression. 124 // 125 // cmp.Comparison 126 // Uses cmp.Result.Success() to check for success or failure. 127 // The comparison is responsible for producing a helpful failure message. 128 // http://pkg.go.dev/gotest.tools/v3/assert/cmp provides many common comparisons. 129 // 130 // error 131 // A nil value is considered success, and a non-nil error is a failure. 132 // The return value of error.Error is used as the failure message. 133 // 134 // Extra details can be added to the failure message using msgAndArgs. msgAndArgs 135 // may be either a single string, or a format string and args that will be 136 // passed to [fmt.Sprintf]. 137 // 138 // Assert uses [testing.TB.FailNow] to fail the test. Like t.FailNow, Assert must be called 139 // from the goroutine running the test function, not from other 140 // goroutines created during the test. Use [Check] from other goroutines. 141 func Assert(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) { 142 if ht, ok := t.(helperT); ok { 143 ht.Helper() 144 } 145 if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) { 146 t.FailNow() 147 } 148 } 149 150 // Check performs a comparison. If the comparison fails the test is marked as 151 // failed, a failure message is printed, and Check returns false. If the comparison 152 // is successful Check returns true. Check may be called from any goroutine. 153 // 154 // See [Assert] for details about the comparison arg and failure messages. 155 func Check(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) bool { 156 if ht, ok := t.(helperT); ok { 157 ht.Helper() 158 } 159 if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) { 160 t.Fail() 161 return false 162 } 163 return true 164 } 165 166 // NilError fails the test immediately if err is not nil, and includes err.Error 167 // in the failure message. 168 // 169 // NilError uses [testing.TB.FailNow] to fail the test. Like t.FailNow, NilError must be 170 // called from the goroutine running the test function, not from other 171 // goroutines created during the test. Use [Check] from other goroutines. 172 func NilError(t TestingT, err error, msgAndArgs ...interface{}) { 173 if ht, ok := t.(helperT); ok { 174 ht.Helper() 175 } 176 if !assert.Eval(t, assert.ArgsAfterT, err, msgAndArgs...) { 177 t.FailNow() 178 } 179 } 180 181 // Equal uses the == operator to assert two values are equal and fails the test 182 // if they are not equal. 183 // 184 // If the comparison fails Equal will use the variable names and types of 185 // x and y as part of the failure message to identify the actual and expected 186 // values. 187 // 188 // assert.Equal(t, actual, expected) 189 // // main_test.go:41: assertion failed: 1 (actual int) != 21 (expected int32) 190 // 191 // If either x or y are a multi-line string the failure message will include a 192 // unified diff of the two values. If the values only differ by whitespace 193 // the unified diff will be augmented by replacing whitespace characters with 194 // visible characters to identify the whitespace difference. 195 // 196 // Equal uses [testing.T.FailNow] to fail the test. Like t.FailNow, Equal must be 197 // called from the goroutine running the test function, not from other 198 // goroutines created during the test. Use [Check] with [cmp.Equal] from other 199 // goroutines. 200 func Equal(t TestingT, x, y interface{}, msgAndArgs ...interface{}) { 201 if ht, ok := t.(helperT); ok { 202 ht.Helper() 203 } 204 if !assert.Eval(t, assert.ArgsAfterT, cmp.Equal(x, y), msgAndArgs...) { 205 t.FailNow() 206 } 207 } 208 209 // DeepEqual uses [github.com/google/go-cmp/cmp] 210 // to assert two values are equal and fails the test if they are not equal. 211 // 212 // Package [gotest.tools/v3/assert/opt] provides some additional 213 // commonly used Options. 214 // 215 // DeepEqual uses [testing.T.FailNow] to fail the test. Like t.FailNow, DeepEqual must be 216 // called from the goroutine running the test function, not from other 217 // goroutines created during the test. Use [Check] with [cmp.DeepEqual] from other 218 // goroutines. 219 func DeepEqual(t TestingT, x, y interface{}, opts ...gocmp.Option) { 220 if ht, ok := t.(helperT); ok { 221 ht.Helper() 222 } 223 if !assert.Eval(t, assert.ArgsAfterT, cmp.DeepEqual(x, y, opts...)) { 224 t.FailNow() 225 } 226 } 227 228 // Error fails the test if err is nil, or if err.Error is not equal to expected. 229 // Both err.Error and expected will be included in the failure message. 230 // Error performs an exact match of the error text. Use [ErrorContains] if only 231 // part of the error message is relevant. Use [ErrorType] or [ErrorIs] to compare 232 // errors by type. 233 // 234 // Error uses [testing.T.FailNow] to fail the test. Like t.FailNow, Error must be 235 // called from the goroutine running the test function, not from other 236 // goroutines created during the test. Use [Check] with [cmp.Error] from other 237 // goroutines. 238 func Error(t TestingT, err error, expected string, msgAndArgs ...interface{}) { 239 if ht, ok := t.(helperT); ok { 240 ht.Helper() 241 } 242 if !assert.Eval(t, assert.ArgsAfterT, cmp.Error(err, expected), msgAndArgs...) { 243 t.FailNow() 244 } 245 } 246 247 // ErrorContains fails the test if err is nil, or if err.Error does not 248 // contain the expected substring. Both err.Error and the expected substring 249 // will be included in the failure message. 250 // 251 // ErrorContains uses [testing.T.FailNow] to fail the test. Like t.FailNow, ErrorContains 252 // must be called from the goroutine running the test function, not from other 253 // goroutines created during the test. Use [Check] with [cmp.ErrorContains] from other 254 // goroutines. 255 func ErrorContains(t TestingT, err error, substring string, msgAndArgs ...interface{}) { 256 if ht, ok := t.(helperT); ok { 257 ht.Helper() 258 } 259 if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...) { 260 t.FailNow() 261 } 262 } 263 264 // ErrorType fails the test if err is nil, or err is not the expected type. 265 // New code should use ErrorIs instead. 266 // 267 // Expected can be one of: 268 // 269 // func(error) bool 270 // The function should return true if the error is the expected type. 271 // 272 // struct{} or *struct{} 273 // A struct or a pointer to a struct. The assertion fails if the error is 274 // not of the same type. 275 // 276 // *interface{} 277 // A pointer to an interface type. The assertion fails if err does not 278 // implement the interface. 279 // 280 // reflect.Type 281 // The assertion fails if err does not implement the reflect.Type. 282 // 283 // ErrorType uses [testing.T.FailNow] to fail the test. Like t.FailNow, ErrorType 284 // must be called from the goroutine running the test function, not from other 285 // goroutines created during the test. Use [Check] with [cmp.ErrorType] from other 286 // goroutines. 287 func ErrorType(t TestingT, err error, expected interface{}, msgAndArgs ...interface{}) { 288 if ht, ok := t.(helperT); ok { 289 ht.Helper() 290 } 291 if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorType(err, expected), msgAndArgs...) { 292 t.FailNow() 293 } 294 } 295 296 // ErrorIs fails the test if err is nil, or the error does not match expected 297 // when compared using errors.Is. See [errors.Is] for 298 // accepted arguments. 299 // 300 // ErrorIs uses [testing.T.FailNow] to fail the test. Like t.FailNow, ErrorIs 301 // must be called from the goroutine running the test function, not from other 302 // goroutines created during the test. Use [Check] with [cmp.ErrorIs] from other 303 // goroutines. 304 func ErrorIs(t TestingT, err error, expected error, msgAndArgs ...interface{}) { 305 if ht, ok := t.(helperT); ok { 306 ht.Helper() 307 } 308 if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorIs(err, expected), msgAndArgs...) { 309 t.FailNow() 310 } 311 } 312