helpers.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package check
  2. import (
  3. "fmt"
  4. "strings"
  5. "time"
  6. )
  7. // TestName returns the current test name in the form "SuiteName.TestName"
  8. func (c *C) TestName() string {
  9. return c.testName
  10. }
  11. // -----------------------------------------------------------------------
  12. // Basic succeeding/failing logic.
  13. // Failed returns whether the currently running test has already failed.
  14. func (c *C) Failed() bool {
  15. return c.status() == failedSt
  16. }
  17. // Fail marks the currently running test as failed.
  18. //
  19. // Something ought to have been previously logged so the developer can tell
  20. // what went wrong. The higher level helper functions will fail the test
  21. // and do the logging properly.
  22. func (c *C) Fail() {
  23. c.setStatus(failedSt)
  24. }
  25. // FailNow marks the currently running test as failed and stops running it.
  26. // Something ought to have been previously logged so the developer can tell
  27. // what went wrong. The higher level helper functions will fail the test
  28. // and do the logging properly.
  29. func (c *C) FailNow() {
  30. c.Fail()
  31. c.stopNow()
  32. }
  33. // Succeed marks the currently running test as succeeded, undoing any
  34. // previous failures.
  35. func (c *C) Succeed() {
  36. c.setStatus(succeededSt)
  37. }
  38. // SucceedNow marks the currently running test as succeeded, undoing any
  39. // previous failures, and stops running the test.
  40. func (c *C) SucceedNow() {
  41. c.Succeed()
  42. c.stopNow()
  43. }
  44. // ExpectFailure informs that the running test is knowingly broken for
  45. // the provided reason. If the test does not fail, an error will be reported
  46. // to raise attention to this fact. This method is useful to temporarily
  47. // disable tests which cover well known problems until a better time to
  48. // fix the problem is found, without forgetting about the fact that a
  49. // failure still exists.
  50. func (c *C) ExpectFailure(reason string) {
  51. if reason == "" {
  52. panic("Missing reason why the test is expected to fail")
  53. }
  54. c.mustFail = true
  55. c.reason = reason
  56. }
  57. // Skip skips the running test for the provided reason. If run from within
  58. // SetUpTest, the individual test being set up will be skipped, and if run
  59. // from within SetUpSuite, the whole suite is skipped.
  60. func (c *C) Skip(reason string) {
  61. if reason == "" {
  62. panic("Missing reason why the test is being skipped")
  63. }
  64. c.reason = reason
  65. c.setStatus(skippedSt)
  66. c.stopNow()
  67. }
  68. // -----------------------------------------------------------------------
  69. // Basic logging.
  70. // GetTestLog returns the current test error output.
  71. func (c *C) GetTestLog() string {
  72. return c.logb.String()
  73. }
  74. // Log logs some information into the test error output.
  75. // The provided arguments are assembled together into a string with fmt.Sprint.
  76. func (c *C) Log(args ...interface{}) {
  77. c.log(args...)
  78. }
  79. // Log logs some information into the test error output.
  80. // The provided arguments are assembled together into a string with fmt.Sprintf.
  81. func (c *C) Logf(format string, args ...interface{}) {
  82. c.logf(format, args...)
  83. }
  84. // Output enables *C to be used as a logger in functions that require only
  85. // the minimum interface of *log.Logger.
  86. func (c *C) Output(calldepth int, s string) error {
  87. d := time.Now().Sub(c.startTime)
  88. msec := d / time.Millisecond
  89. sec := d / time.Second
  90. min := d / time.Minute
  91. c.Logf("[LOG] %d:%02d.%03d %s", min, sec%60, msec%1000, s)
  92. return nil
  93. }
  94. // Error logs an error into the test error output and marks the test as failed.
  95. // The provided arguments are assembled together into a string with fmt.Sprint.
  96. func (c *C) Error(args ...interface{}) {
  97. c.logCaller(1)
  98. c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...)))
  99. c.logNewLine()
  100. c.Fail()
  101. }
  102. // Errorf logs an error into the test error output and marks the test as failed.
  103. // The provided arguments are assembled together into a string with fmt.Sprintf.
  104. func (c *C) Errorf(format string, args ...interface{}) {
  105. c.logCaller(1)
  106. c.logString(fmt.Sprintf("Error: "+format, args...))
  107. c.logNewLine()
  108. c.Fail()
  109. }
  110. // Fatal logs an error into the test error output, marks the test as failed, and
  111. // stops the test execution. The provided arguments are assembled together into
  112. // a string with fmt.Sprint.
  113. func (c *C) Fatal(args ...interface{}) {
  114. c.logCaller(1)
  115. c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...)))
  116. c.logNewLine()
  117. c.FailNow()
  118. }
  119. // Fatlaf logs an error into the test error output, marks the test as failed, and
  120. // stops the test execution. The provided arguments are assembled together into
  121. // a string with fmt.Sprintf.
  122. func (c *C) Fatalf(format string, args ...interface{}) {
  123. c.logCaller(1)
  124. c.logString(fmt.Sprint("Error: ", fmt.Sprintf(format, args...)))
  125. c.logNewLine()
  126. c.FailNow()
  127. }
  128. // -----------------------------------------------------------------------
  129. // Generic checks and assertions based on checkers.
  130. // Check verifies if the first value matches the expected value according
  131. // to the provided checker. If they do not match, an error is logged, the
  132. // test is marked as failed, and the test execution continues.
  133. //
  134. // Some checkers may not need the expected argument (e.g. IsNil).
  135. //
  136. // Extra arguments provided to the function are logged next to the reported
  137. // problem when the matching fails.
  138. func (c *C) Check(obtained interface{}, checker Checker, args ...interface{}) bool {
  139. return c.internalCheck("Check", obtained, checker, args...)
  140. }
  141. // Assert ensures that the first value matches the expected value according
  142. // to the provided checker. If they do not match, an error is logged, the
  143. // test is marked as failed, and the test execution stops.
  144. //
  145. // Some checkers may not need the expected argument (e.g. IsNil).
  146. //
  147. // Extra arguments provided to the function are logged next to the reported
  148. // problem when the matching fails.
  149. func (c *C) Assert(obtained interface{}, checker Checker, args ...interface{}) {
  150. if !c.internalCheck("Assert", obtained, checker, args...) {
  151. c.stopNow()
  152. }
  153. }
  154. func (c *C) internalCheck(funcName string, obtained interface{}, checker Checker, args ...interface{}) bool {
  155. if checker == nil {
  156. c.logCaller(2)
  157. c.logString(fmt.Sprintf("%s(obtained, nil!?, ...):", funcName))
  158. c.logString("Oops.. you've provided a nil checker!")
  159. c.logNewLine()
  160. c.Fail()
  161. return false
  162. }
  163. // If the last argument is a bug info, extract it out.
  164. var comment CommentInterface
  165. if len(args) > 0 {
  166. if c, ok := args[len(args)-1].(CommentInterface); ok {
  167. comment = c
  168. args = args[:len(args)-1]
  169. }
  170. }
  171. params := append([]interface{}{obtained}, args...)
  172. info := checker.Info()
  173. if len(params) != len(info.Params) {
  174. names := append([]string{info.Params[0], info.Name}, info.Params[1:]...)
  175. c.logCaller(2)
  176. c.logString(fmt.Sprintf("%s(%s):", funcName, strings.Join(names, ", ")))
  177. c.logString(fmt.Sprintf("Wrong number of parameters for %s: want %d, got %d", info.Name, len(names), len(params)+1))
  178. c.logNewLine()
  179. c.Fail()
  180. return false
  181. }
  182. // Copy since it may be mutated by Check.
  183. names := append([]string{}, info.Params...)
  184. // Do the actual check.
  185. result, error := checker.Check(params, names)
  186. if !result || error != "" {
  187. c.logCaller(2)
  188. for i := 0; i != len(params); i++ {
  189. c.logValue(names[i], params[i])
  190. }
  191. if comment != nil {
  192. c.logString(comment.CheckCommentString())
  193. }
  194. if error != "" {
  195. c.logString(error)
  196. }
  197. c.logNewLine()
  198. c.Fail()
  199. return false
  200. }
  201. return true
  202. }