123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- package check
- import (
- "fmt"
- "strings"
- "time"
- )
- // TestName returns the current test name in the form "SuiteName.TestName"
- func (c *C) TestName() string {
- return c.testName
- }
- // -----------------------------------------------------------------------
- // Basic succeeding/failing logic.
- // Failed returns whether the currently running test has already failed.
- func (c *C) Failed() bool {
- return c.status() == failedSt
- }
- // Fail marks the currently running test as failed.
- //
- // Something ought to have been previously logged so the developer can tell
- // what went wrong. The higher level helper functions will fail the test
- // and do the logging properly.
- func (c *C) Fail() {
- c.setStatus(failedSt)
- }
- // FailNow marks the currently running test as failed and stops running it.
- // Something ought to have been previously logged so the developer can tell
- // what went wrong. The higher level helper functions will fail the test
- // and do the logging properly.
- func (c *C) FailNow() {
- c.Fail()
- c.stopNow()
- }
- // Succeed marks the currently running test as succeeded, undoing any
- // previous failures.
- func (c *C) Succeed() {
- c.setStatus(succeededSt)
- }
- // SucceedNow marks the currently running test as succeeded, undoing any
- // previous failures, and stops running the test.
- func (c *C) SucceedNow() {
- c.Succeed()
- c.stopNow()
- }
- // ExpectFailure informs that the running test is knowingly broken for
- // the provided reason. If the test does not fail, an error will be reported
- // to raise attention to this fact. This method is useful to temporarily
- // disable tests which cover well known problems until a better time to
- // fix the problem is found, without forgetting about the fact that a
- // failure still exists.
- func (c *C) ExpectFailure(reason string) {
- if reason == "" {
- panic("Missing reason why the test is expected to fail")
- }
- c.mustFail = true
- c.reason = reason
- }
- // Skip skips the running test for the provided reason. If run from within
- // SetUpTest, the individual test being set up will be skipped, and if run
- // from within SetUpSuite, the whole suite is skipped.
- func (c *C) Skip(reason string) {
- if reason == "" {
- panic("Missing reason why the test is being skipped")
- }
- c.reason = reason
- c.setStatus(skippedSt)
- c.stopNow()
- }
- // -----------------------------------------------------------------------
- // Basic logging.
- // GetTestLog returns the current test error output.
- func (c *C) GetTestLog() string {
- return c.logb.String()
- }
- // Log logs some information into the test error output.
- // The provided arguments are assembled together into a string with fmt.Sprint.
- func (c *C) Log(args ...interface{}) {
- c.log(args...)
- }
- // Log logs some information into the test error output.
- // The provided arguments are assembled together into a string with fmt.Sprintf.
- func (c *C) Logf(format string, args ...interface{}) {
- c.logf(format, args...)
- }
- // Output enables *C to be used as a logger in functions that require only
- // the minimum interface of *log.Logger.
- func (c *C) Output(calldepth int, s string) error {
- d := time.Now().Sub(c.startTime)
- msec := d / time.Millisecond
- sec := d / time.Second
- min := d / time.Minute
- c.Logf("[LOG] %d:%02d.%03d %s", min, sec%60, msec%1000, s)
- return nil
- }
- // Error logs an error into the test error output and marks the test as failed.
- // The provided arguments are assembled together into a string with fmt.Sprint.
- func (c *C) Error(args ...interface{}) {
- c.logCaller(1)
- c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...)))
- c.logNewLine()
- c.Fail()
- }
- // Errorf logs an error into the test error output and marks the test as failed.
- // The provided arguments are assembled together into a string with fmt.Sprintf.
- func (c *C) Errorf(format string, args ...interface{}) {
- c.logCaller(1)
- c.logString(fmt.Sprintf("Error: "+format, args...))
- c.logNewLine()
- c.Fail()
- }
- // Fatal logs an error into the test error output, marks the test as failed, and
- // stops the test execution. The provided arguments are assembled together into
- // a string with fmt.Sprint.
- func (c *C) Fatal(args ...interface{}) {
- c.logCaller(1)
- c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...)))
- c.logNewLine()
- c.FailNow()
- }
- // Fatlaf logs an error into the test error output, marks the test as failed, and
- // stops the test execution. The provided arguments are assembled together into
- // a string with fmt.Sprintf.
- func (c *C) Fatalf(format string, args ...interface{}) {
- c.logCaller(1)
- c.logString(fmt.Sprint("Error: ", fmt.Sprintf(format, args...)))
- c.logNewLine()
- c.FailNow()
- }
- // -----------------------------------------------------------------------
- // Generic checks and assertions based on checkers.
- // Check verifies if the first value matches the expected value according
- // to the provided checker. If they do not match, an error is logged, the
- // test is marked as failed, and the test execution continues.
- //
- // Some checkers may not need the expected argument (e.g. IsNil).
- //
- // Extra arguments provided to the function are logged next to the reported
- // problem when the matching fails.
- func (c *C) Check(obtained interface{}, checker Checker, args ...interface{}) bool {
- return c.internalCheck("Check", obtained, checker, args...)
- }
- // Assert ensures that the first value matches the expected value according
- // to the provided checker. If they do not match, an error is logged, the
- // test is marked as failed, and the test execution stops.
- //
- // Some checkers may not need the expected argument (e.g. IsNil).
- //
- // Extra arguments provided to the function are logged next to the reported
- // problem when the matching fails.
- func (c *C) Assert(obtained interface{}, checker Checker, args ...interface{}) {
- if !c.internalCheck("Assert", obtained, checker, args...) {
- c.stopNow()
- }
- }
- func (c *C) internalCheck(funcName string, obtained interface{}, checker Checker, args ...interface{}) bool {
- if checker == nil {
- c.logCaller(2)
- c.logString(fmt.Sprintf("%s(obtained, nil!?, ...):", funcName))
- c.logString("Oops.. you've provided a nil checker!")
- c.logNewLine()
- c.Fail()
- return false
- }
- // If the last argument is a bug info, extract it out.
- var comment CommentInterface
- if len(args) > 0 {
- if c, ok := args[len(args)-1].(CommentInterface); ok {
- comment = c
- args = args[:len(args)-1]
- }
- }
- params := append([]interface{}{obtained}, args...)
- info := checker.Info()
- if len(params) != len(info.Params) {
- names := append([]string{info.Params[0], info.Name}, info.Params[1:]...)
- c.logCaller(2)
- c.logString(fmt.Sprintf("%s(%s):", funcName, strings.Join(names, ", ")))
- c.logString(fmt.Sprintf("Wrong number of parameters for %s: want %d, got %d", info.Name, len(names), len(params)+1))
- c.logNewLine()
- c.Fail()
- return false
- }
- // Copy since it may be mutated by Check.
- names := append([]string{}, info.Params...)
- // Do the actual check.
- result, error := checker.Check(params, names)
- if !result || error != "" {
- c.logCaller(2)
- for i := 0; i != len(params); i++ {
- c.logValue(names[i], params[i])
- }
- if comment != nil {
- c.logString(comment.CheckCommentString())
- }
- if error != "" {
- c.logString(error)
- }
- c.logNewLine()
- c.Fail()
- return false
- }
- return true
- }
|