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 }