assert.go 11 KB

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