1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package testing provides support for automated testing of Go packages.
6 // It is intended to be used in concert with the ``gotest'' utility, which automates
7 // execution of any function of the form
8 // func TestXxx(*testing.T)
9 // where Xxx can be any alphanumeric string (but the first letter must not be in
10 // [a-z]) and serves to identify the test routine.
11 // These TestXxx routines should be declared within the package they are testing.
13 // Functions of the form
14 // func BenchmarkXxx(*testing.B)
15 // are considered benchmarks, and are executed by gotest when the -test.bench
18 // A sample benchmark function looks like this:
19 // func BenchmarkHello(b *testing.B) {
20 // for i := 0; i < b.N; i++ {
21 // fmt.Sprintf("hello")
24 // The benchmark package will vary b.N until the benchmark function lasts
25 // long enough to be timed reliably. The output
26 // testing.BenchmarkHello 500000 4076 ns/op
27 // means that the loop ran 500000 times at a speed of 4076 ns per loop.
29 // If a benchmark needs some expensive setup before running, the timer
31 // func BenchmarkBigLen(b *testing.B) {
35 // for i := 0; i < b.N; i++ {
53 // The short flag requests that tests run more quickly, but its functionality
54 // is provided by test writers themselves. The testing package is just its
55 // home. The all.bash installation script sets it to make installation more
56 // efficient, but by default the flag is off so a plain "gotest" will do a
57 // full test of the package.
58 short = flag.Bool("test.short", false, "run smaller test suite to save time")
60 // Report as tests are run; default is silent for success.
61 chatty = flag.Bool("test.v", false, "verbose: print additional output")
62 match = flag.String("test.run", "", "regular expression to select tests to run")
63 memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
64 memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
65 cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
66 timeout = flag.Int64("test.timeout", 0, "if > 0, sets time limit for tests in seconds")
67 cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
68 parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
73 // Short reports whether the -test.short flag is set.
78 // Insert final newline if needed and tabs after internal newlines.
79 func tabify(s string) string {
81 if n > 0 && s[n-1] != '\n' {
85 for i := 0; i < n-1; i++ { // -1 to avoid final newline
87 return s[0:i+1] + "\t" + tabify(s[i+1:n])
93 // T is a type passed to Test functions to manage test state and support formatted test logs.
94 // Logs are accumulated during execution and dumped to standard error when done.
96 name string // Name of test.
97 errors string // Error string from test.
98 failed bool // Test has failed.
99 ch chan *T // Output for serial tests.
100 startParallel chan bool // Parallel tests will wait on this.
101 ns int64 // Duration of test in nanoseconds.
104 // Fail marks the Test function as having failed but continues execution.
105 func (t *T) Fail() { t.failed = true }
107 // Failed returns whether the Test function has failed.
108 func (t *T) Failed() bool { return t.failed }
110 // FailNow marks the Test function as having failed and stops its execution.
111 // Execution will continue at the next Test.
112 func (t *T) FailNow() {
113 t.ns = time.Nanoseconds() - t.ns
119 // Log formats its arguments using default formatting, analogous to Print(),
120 // and records the text in the error log.
121 func (t *T) Log(args ...interface{}) { t.errors += "\t" + tabify(fmt.Sprintln(args...)) }
123 // Logf formats its arguments according to the format, analogous to Printf(),
124 // and records the text in the error log.
125 func (t *T) Logf(format string, args ...interface{}) {
126 t.errors += "\t" + tabify(fmt.Sprintf(format, args...))
129 // Error is equivalent to Log() followed by Fail().
130 func (t *T) Error(args ...interface{}) {
135 // Errorf is equivalent to Logf() followed by Fail().
136 func (t *T) Errorf(format string, args ...interface{}) {
137 t.Logf(format, args...)
141 // Fatal is equivalent to Log() followed by FailNow().
142 func (t *T) Fatal(args ...interface{}) {
147 // Fatalf is equivalent to Logf() followed by FailNow().
148 func (t *T) Fatalf(format string, args ...interface{}) {
149 t.Logf(format, args...)
153 // Parallel signals that this test is to be run in parallel with (and only with)
154 // other parallel tests in this CPU group.
155 func (t *T) Parallel() {
156 t.ch <- nil // Release main testing loop
157 <-t.startParallel // Wait for serial tests to finish
160 // An internal type but exported because it is cross-package; part of the implementation
162 type InternalTest struct {
167 func tRunner(t *T, test *InternalTest) {
168 t.ns = time.Nanoseconds()
170 t.ns = time.Nanoseconds() - t.ns
174 // An internal function but exported because it is cross-package; part of the implementation
176 func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
182 testOk := RunTests(matchString, tests)
183 exampleOk := RunExamples(examples)
184 if !testOk || !exampleOk {
185 fmt.Fprintln(os.Stderr, "FAIL")
188 fmt.Fprintln(os.Stderr, "PASS")
190 RunBenchmarks(matchString, benchmarks)
195 tstr := fmt.Sprintf("(%.2f seconds)", float64(t.ns)/1e9)
196 format := "--- %s: %s %s\n%s"
198 fmt.Fprintf(os.Stderr, format, "FAIL", t.name, tstr, t.errors)
200 fmt.Fprintf(os.Stderr, format, "PASS", t.name, tstr, t.errors)
204 func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
207 fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
211 for _, procs := range cpuList {
212 runtime.GOMAXPROCS(procs)
215 startParallel := make(chan bool)
217 for i := 0; i < len(tests); i++ {
218 matched, err := matchString(*match, tests[i].Name)
220 println("invalid regexp for -test.run:", err.Error())
226 testName := tests[i].Name
228 testName = fmt.Sprintf("%s-%d", tests[i].Name, procs)
230 t := &T{ch: ch, name: testName, startParallel: startParallel}
232 println("=== RUN", t.name)
234 go tRunner(t, &tests[i])
236 if out == nil { // Parallel run.
241 ok = ok && !out.failed
245 for numParallel+running > 0 {
246 if running < *parallel && numParallel > 0 {
247 startParallel <- true
261 // before runs before all testing.
263 if *memProfileRate > 0 {
264 runtime.MemProfileRate = *memProfileRate
266 if *cpuProfile != "" {
267 f, err := os.Create(*cpuProfile)
269 fmt.Fprintf(os.Stderr, "testing: %s", err)
272 if err := pprof.StartCPUProfile(f); err != nil {
273 fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err)
277 // Could save f so after can call f.Close; not worth the effort.
282 // after runs after all testing.
284 if *cpuProfile != "" {
285 pprof.StopCPUProfile() // flushes profile to disk
287 if *memProfile != "" {
288 f, err := os.Create(*memProfile)
290 fmt.Fprintf(os.Stderr, "testing: %s", err)
293 if err = pprof.WriteHeapProfile(f); err != nil {
294 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *memProfile, err)
300 var timer *time.Timer
302 // startAlarm starts an alarm if requested.
305 timer = time.AfterFunc(*timeout*1e9, alarm)
309 // stopAlarm turns off the alarm.
316 // alarm is called if the timeout expires.
318 panic("test timed out")
321 func parseCpuList() {
322 if len(*cpuListStr) == 0 {
323 cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
325 for _, val := range strings.Split(*cpuListStr, ",") {
326 cpu, err := strconv.Atoi(val)
327 if err != nil || cpu <= 0 {
328 println("invalid value for -test.cpu")
331 cpuList = append(cpuList, cpu)