1package check 2 3import ( 4 "bufio" 5 "flag" 6 "fmt" 7 "os" 8 "testing" 9 "time" 10) 11 12// ----------------------------------------------------------------------- 13// Test suite registry. 14 15var allSuites []interface{} 16 17// Suite registers the given value as a test suite to be run. Any methods 18// starting with the Test prefix in the given value will be considered as 19// a test method. 20func Suite(suite interface{}) interface{} { 21 allSuites = append(allSuites, suite) 22 return suite 23} 24 25// ----------------------------------------------------------------------- 26// Public running interface. 27 28var ( 29 oldFilterFlag = flag.String("gocheck.f", "", "Regular expression selecting which tests and/or suites to run") 30 oldVerboseFlag = flag.Bool("gocheck.v", false, "Verbose mode") 31 oldStreamFlag = flag.Bool("gocheck.vv", false, "Super verbose mode (disables output caching)") 32 oldBenchFlag = flag.Bool("gocheck.b", false, "Run benchmarks") 33 oldBenchTime = flag.Duration("gocheck.btime", 1*time.Second, "approximate run time for each benchmark") 34 oldListFlag = flag.Bool("gocheck.list", false, "List the names of all tests that will be run") 35 oldWorkFlag = flag.Bool("gocheck.work", false, "Display and do not remove the test working directory") 36 37 newFilterFlag = flag.String("check.f", "", "Regular expression selecting which tests and/or suites to run") 38 newVerboseFlag = flag.Bool("check.v", false, "Verbose mode") 39 newStreamFlag = flag.Bool("check.vv", false, "Super verbose mode (disables output caching)") 40 newBenchFlag = flag.Bool("check.b", false, "Run benchmarks") 41 newBenchTime = flag.Duration("check.btime", 1*time.Second, "approximate run time for each benchmark") 42 newBenchMem = flag.Bool("check.bmem", false, "Report memory benchmarks") 43 newListFlag = flag.Bool("check.list", false, "List the names of all tests that will be run") 44 newWorkFlag = flag.Bool("check.work", false, "Display and do not remove the test working directory") 45) 46 47// TestingT runs all test suites registered with the Suite function, 48// printing results to stdout, and reporting any failures back to 49// the "testing" package. 50func TestingT(testingT *testing.T) { 51 benchTime := *newBenchTime 52 if benchTime == 1*time.Second { 53 benchTime = *oldBenchTime 54 } 55 conf := &RunConf{ 56 Filter: *oldFilterFlag + *newFilterFlag, 57 Verbose: *oldVerboseFlag || *newVerboseFlag, 58 Stream: *oldStreamFlag || *newStreamFlag, 59 Benchmark: *oldBenchFlag || *newBenchFlag, 60 BenchmarkTime: benchTime, 61 BenchmarkMem: *newBenchMem, 62 KeepWorkDir: *oldWorkFlag || *newWorkFlag, 63 } 64 if *oldListFlag || *newListFlag { 65 w := bufio.NewWriter(os.Stdout) 66 for _, name := range ListAll(conf) { 67 fmt.Fprintln(w, name) 68 } 69 w.Flush() 70 return 71 } 72 result := RunAll(conf) 73 println(result.String()) 74 if !result.Passed() { 75 testingT.Fail() 76 } 77} 78 79// RunAll runs all test suites registered with the Suite function, using the 80// provided run configuration. 81func RunAll(runConf *RunConf) *Result { 82 result := Result{} 83 for _, suite := range allSuites { 84 result.Add(Run(suite, runConf)) 85 } 86 return &result 87} 88 89// Run runs the provided test suite using the provided run configuration. 90func Run(suite interface{}, runConf *RunConf) *Result { 91 runner := newSuiteRunner(suite, runConf) 92 return runner.run() 93} 94 95// ListAll returns the names of all the test functions registered with the 96// Suite function that will be run with the provided run configuration. 97func ListAll(runConf *RunConf) []string { 98 var names []string 99 for _, suite := range allSuites { 100 names = append(names, List(suite, runConf)...) 101 } 102 return names 103} 104 105// List returns the names of the test functions in the given 106// suite that will be run with the provided run configuration. 107func List(suite interface{}, runConf *RunConf) []string { 108 var names []string 109 runner := newSuiteRunner(suite, runConf) 110 for _, t := range runner.tests { 111 names = append(names, t.String()) 112 } 113 return names 114} 115 116// ----------------------------------------------------------------------- 117// Result methods. 118 119func (r *Result) Add(other *Result) { 120 r.Succeeded += other.Succeeded 121 r.Skipped += other.Skipped 122 r.Failed += other.Failed 123 r.Panicked += other.Panicked 124 r.FixturePanicked += other.FixturePanicked 125 r.ExpectedFailures += other.ExpectedFailures 126 r.Missed += other.Missed 127 if r.WorkDir != "" && other.WorkDir != "" { 128 r.WorkDir += ":" + other.WorkDir 129 } else if other.WorkDir != "" { 130 r.WorkDir = other.WorkDir 131 } 132} 133 134func (r *Result) Passed() bool { 135 return (r.Failed == 0 && r.Panicked == 0 && 136 r.FixturePanicked == 0 && r.Missed == 0 && 137 r.RunError == nil) 138} 139 140func (r *Result) String() string { 141 if r.RunError != nil { 142 return "ERROR: " + r.RunError.Error() 143 } 144 145 var value string 146 if r.Failed == 0 && r.Panicked == 0 && r.FixturePanicked == 0 && 147 r.Missed == 0 { 148 value = "OK: " 149 } else { 150 value = "OOPS: " 151 } 152 value += fmt.Sprintf("%d passed", r.Succeeded) 153 if r.Skipped != 0 { 154 value += fmt.Sprintf(", %d skipped", r.Skipped) 155 } 156 if r.ExpectedFailures != 0 { 157 value += fmt.Sprintf(", %d expected failures", r.ExpectedFailures) 158 } 159 if r.Failed != 0 { 160 value += fmt.Sprintf(", %d FAILED", r.Failed) 161 } 162 if r.Panicked != 0 { 163 value += fmt.Sprintf(", %d PANICKED", r.Panicked) 164 } 165 if r.FixturePanicked != 0 { 166 value += fmt.Sprintf(", %d FIXTURE-PANICKED", r.FixturePanicked) 167 } 168 if r.Missed != 0 { 169 value += fmt.Sprintf(", %d MISSED", r.Missed) 170 } 171 if r.WorkDir != "" { 172 value += "\nWORK=" + r.WorkDir 173 } 174 return value 175} 176