launchpad.net/gocheck@v0.0.0-20140225173054-000000000087/helpers.go (about)

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