assertion.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package httpexpect
  2. // AssertionType defines type of performed assertion.
  3. type AssertionType uint
  4. //go:generate stringer -type=AssertionType
  5. const (
  6. // Check if the invocation is correct
  7. AssertUsage AssertionType = iota
  8. // Check if the operation succeeded
  9. AssertOperation
  10. // Check expression: [Actual] has appropriate type
  11. AssertType
  12. AssertNotType
  13. // Check expression: [Actual] has valid value
  14. AssertValid
  15. AssertNotValid
  16. // Check expression: [Actual] is nil
  17. AssertNil
  18. AssertNotNil
  19. // Check expression: [Actual] is empty
  20. AssertEmpty
  21. AssertNotEmpty
  22. // Check expression: [Actual] is equal to [Expected]
  23. // If [Delta] is set, it specifies allowed difference between values
  24. AssertEqual
  25. AssertNotEqual
  26. // Check expression: [Actual] < [Expected]
  27. AssertLt
  28. // Check expression: [Actual] <= [Expected]
  29. AssertLe
  30. // Check expression: [Actual] > [Expected]
  31. AssertGt
  32. // Check expression: [Actual] >= [Expected]
  33. AssertGe
  34. // Check expression: [Actual] belongs to inclusive range [Expected]
  35. // [Expected] stores AssertionRange with Min and Max values
  36. AssertInRange
  37. AssertNotInRange
  38. // Check expression: [Actual] matches json schema [Expected]
  39. // [Expected] stores map with parsed schema or string with schema uri
  40. AssertMatchSchema
  41. AssertNotMatchSchema
  42. // Check expression: [Actual] matches json path [Expected]
  43. // [Expected] stores a string with json path
  44. AssertMatchPath
  45. AssertNotMatchPath
  46. // Check expression: [Actual] matches regex [Expected]
  47. // [Expected] stores a string with regular expression
  48. AssertMatchRegexp
  49. AssertNotMatchRegexp
  50. // Check expression: [Actual] matches format [Expected]
  51. // [Expected] stores expected format or format list (AssertionList)
  52. AssertMatchFormat
  53. AssertNotMatchFormat
  54. // Check expression: [Actual] contains key [Expected]
  55. AssertContainsKey
  56. AssertNotContainsKey
  57. // Check expression: [Actual] contains element [Expected]
  58. AssertContainsElement
  59. AssertNotContainsElement
  60. // Check expression: [Actual] contains subset [Expected]
  61. AssertContainsSubset
  62. AssertNotContainsSubset
  63. // Check expression: [Actual] belongs to list [Expected]
  64. // [Expected] stores AssertionList with allowed values
  65. AssertBelongs
  66. AssertNotBelongs
  67. )
  68. // AssertionSeverity defines how assertion failure should be treated.
  69. type AssertionSeverity uint
  70. //go:generate stringer -type=AssertionSeverity
  71. const (
  72. // This assertion failure should mark current test as failed.
  73. // Typically handler will call t.Errorf().
  74. // This severity is used for most assertions.
  75. SeverityError AssertionSeverity = iota
  76. // This assertion failure is informational only, it can be logged,
  77. // but should not cause test failure.
  78. // Typically handler will call t.Logf(), or just ignore assertion.
  79. // This severity is used for assertions issued inside predicate functions,
  80. // e.g. in Array.Filter and Object.Filter.
  81. SeverityLog
  82. )
  83. // AssertionContext provides context where the assetion happened.
  84. type AssertionContext struct {
  85. // Name of the running test
  86. // Usually comes from testing.T
  87. TestName string
  88. // Name of request being sent
  89. // Comes from Request.WithName()
  90. RequestName string
  91. // Chain of nested assertion names
  92. // Example value:
  93. // {`Request("GET")`, `Expect()`, `JSON()`, `NotNull()`}
  94. Path []string
  95. // Chain of nested assertion names starting from alias
  96. // When alias is not set, AliasedPath has the same value as Path
  97. // Example value:
  98. // {`foo`, `NotNull()`} // alias named foo
  99. AliasedPath []string
  100. // Request being sent
  101. // May be nil if request was not yet sent
  102. Request *Request
  103. // Response being matched
  104. // May be nil if response was not yet received
  105. Response *Response
  106. // Environment shared between tests
  107. // Comes from Expect instance
  108. Environment *Environment
  109. // Whether reporter is known to output to testing.TB
  110. // For example, true when reporter is testing.T or testify-based reporter.
  111. TestingTB bool
  112. }
  113. // AssertionFailure provides detailed information about failed assertion.
  114. //
  115. // [Type] and [Errors] fields are set for all assertions.
  116. // [Actual], [Expected], [Reference], and [Delta] fields are set only for
  117. // certain assertion types.
  118. //
  119. // The value itself is stored in [Actual.Value], [Expected.Value], etc.
  120. // It allows to distinguish whether the value is not present at all,
  121. // or is present but is nil.
  122. //
  123. // [Actual] stores the value being examined.
  124. //
  125. // Exact meaning of [Expected] depends on assertion type. It may be the value
  126. // to which [Actual] was compared, or range to which [Actual] should belong,
  127. // or pattern with which [Actual] should match, or element which [Actual]
  128. // should contain, and so on.
  129. //
  130. // If [Reference] is set, it stores the value from which the check originated.
  131. // For example, the user asked to check for unordered equality of arrays
  132. // A and B. During comparison, a check failed that array A contains element E
  133. // from array B. In this case [Actual] will be set to A (actually observed array),
  134. // [Expected] will be set to E (expected but missing element), and [Reference]
  135. // will be set to B (reference array that originated the check).
  136. //
  137. // If [Delta] is set, it stores maximum allowed difference between [Actual]
  138. // and [Expected] values.
  139. //
  140. // For further details, see comments for corresponding AssertionType constant.
  141. type AssertionFailure struct {
  142. // Type of failed assertion
  143. Type AssertionType
  144. // Severity of failure
  145. Severity AssertionSeverity
  146. // Deprecated: use Severity
  147. IsFatal bool
  148. // List of error messages
  149. Errors []error
  150. // Actually observed value
  151. Actual *AssertionValue
  152. // Expected value
  153. Expected *AssertionValue
  154. // Reference value
  155. Reference *AssertionValue
  156. // Allowed delta between actual and expected
  157. Delta *AssertionValue
  158. // Stacktrace of the failure
  159. Stacktrace []StacktraceEntry
  160. }
  161. // AssertionValue holds expected or actual value
  162. type AssertionValue struct {
  163. Value interface{}
  164. }
  165. // AssertionRange holds inclusive range for allowed values
  166. type AssertionRange struct {
  167. Min interface{}
  168. Max interface{}
  169. }
  170. // AssertionList holds list of allowed values
  171. type AssertionList []interface{}
  172. // AssertionHandler takes care of formatting and reporting test Failure or Success.
  173. //
  174. // You can log every performed assertion, or report only failures. You can implement
  175. // custom formatting, for example, provide a JSON output for ulterior processing.
  176. //
  177. // Usually you don't need to implement AssertionHandler; instead you can implement
  178. // Reporter, which is much simpler, and use it with DefaultAssertionHandler.
  179. type AssertionHandler interface {
  180. // Invoked every time when an assertion succeeded.
  181. // May ignore failure, or log it, e.g. using t.Logf().
  182. Success(*AssertionContext)
  183. // Invoked every time when an assertion failed.
  184. // Handling depends on Failure.Severity field:
  185. // - for SeverityError, reports failure to testing suite, e.g. using t.Errorf()
  186. // - for SeverityLog, ignores failure, or logs it, e.g. using t.Logf()
  187. Failure(*AssertionContext, *AssertionFailure)
  188. }
  189. // DefaultAssertionHandler is default implementation for AssertionHandler.
  190. //
  191. // - Formatter is used to format success and failure messages
  192. // - Reporter is used to report formatted fatal failure messages
  193. // - Logger is used to print formatted success and non-fatal failure messages
  194. //
  195. // Formatter and Reporter are required. Logger is optional.
  196. // By default httpexpect creates DefaultAssertionHandler without Logger.
  197. type DefaultAssertionHandler struct {
  198. Formatter Formatter
  199. Reporter Reporter
  200. Logger Logger
  201. }
  202. // Success implements AssertionHandler.Success.
  203. func (h *DefaultAssertionHandler) Success(ctx *AssertionContext) {
  204. if h.Formatter == nil {
  205. panic("DefaultAssertionHandler.Formatter is nil")
  206. }
  207. if h.Logger == nil {
  208. return
  209. }
  210. msg := h.Formatter.FormatSuccess(ctx)
  211. h.Logger.Logf("%s", msg)
  212. }
  213. // Failure implements AssertionHandler.Failure.
  214. func (h *DefaultAssertionHandler) Failure(
  215. ctx *AssertionContext, failure *AssertionFailure,
  216. ) {
  217. if h.Formatter == nil {
  218. panic("DefaultAssertionHandler.Formatter is nil")
  219. }
  220. switch failure.Severity {
  221. case SeverityError:
  222. if h.Reporter == nil {
  223. panic("DefaultAssertionHandler.Reporter is nil")
  224. }
  225. msg := h.Formatter.FormatFailure(ctx, failure)
  226. h.Reporter.Errorf("%s", msg)
  227. case SeverityLog:
  228. if h.Logger == nil {
  229. return
  230. }
  231. msg := h.Formatter.FormatFailure(ctx, failure)
  232. h.Logger.Logf("%s", msg)
  233. }
  234. }