cmd/go, testing: indicate when no tests are run

For example, testing the current directory:

	$ go test -run XXX
	testing: warning: no tests to run
	PASS
	ok  	testing	0.013s
	$

And in a summary:

	$ go test -run XXX testing
	ok  	testing	0.013s [no tests to run]
	$

These make it easy to spot when the -run regexp hasn't matched anything
or there are no tests. Previously the message was printed in the "current directory"
case when there were no tests at all, but not for no matches, and either way
was not surfaced in the directory list summary form.

Fixes #15211.

Change-Id: I1c82a423d6bd429fb991c9ca964c9d26c96fd3c5
Reviewed-on: https://go-review.googlesource.com/22341
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
This commit is contained in:
Caio Marcelo de Oliveira Filho 2016-04-20 14:29:30 -03:00 committed by Russ Cox
parent 95abb5a36a
commit ead08e91f6
9 changed files with 194 additions and 17 deletions

View file

@ -259,10 +259,12 @@ type common struct {
output []byte // Output generated by test or benchmark.
w io.Writer // For flushToParent.
chatty bool // A copy of the chatty flag.
ran bool // Test or benchmark (or one of its subtests) was executed.
failed bool // Test or benchmark has failed.
skipped bool // Test of benchmark has been skipped.
finished bool // Test function has completed.
done bool // Test is finished and all subtests have completed.
hasSub bool
parent *common
level int // Nesting depth of test or benchmark.
@ -410,6 +412,15 @@ func (c *common) Name() string {
return c.name
}
func (c *common) setRan() {
if c.parent != nil {
c.parent.setRan()
}
c.mu.Lock()
defer c.mu.Unlock()
c.ran = true
}
// Fail marks the function as having failed but continues execution.
func (c *common) Fail() {
if c.parent != nil {
@ -616,6 +627,9 @@ func tRunner(t *T, fn func(t *T)) {
// Do not lock t.done to allow race detector to detect race in case
// the user does not appropriately synchronizes a goroutine.
t.done = true
if t.parent != nil && !t.hasSub {
t.setRan()
}
t.signal <- true
}()
@ -627,6 +641,7 @@ func tRunner(t *T, fn func(t *T)) {
// Run runs f as a subtest of t called name. It reports whether f succeeded.
// Run will block until all its parallel subtests have completed.
func (t *T) Run(name string, f func(t *T)) bool {
t.hasSub = true
testName, ok := t.context.match.fullName(&t.common, name)
if !ok {
return true
@ -753,14 +768,17 @@ func (m *M) Run() int {
before()
startAlarm()
haveExamples = len(m.examples) > 0
testOk := RunTests(m.matchString, m.tests)
exampleOk := RunExamples(m.matchString, m.examples)
stopAlarm()
if !testOk || !exampleOk || !runBenchmarksInternal(m.matchString, m.benchmarks) {
testRan, testOk := runTests(m.matchString, m.tests)
exampleRan, exampleOk := runExamples(m.matchString, m.examples)
if !testRan && !exampleRan {
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
}
if !testOk || !exampleOk || !runBenchmarks(m.matchString, m.benchmarks) {
fmt.Println("FAIL")
after()
return 1
}
fmt.Println("PASS")
after()
return 0
@ -783,12 +801,18 @@ func (t *T) report() {
}
}
// An internal function but exported because it is cross-package; part of the implementation
// of the "go test" command.
func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
ok = true
if len(tests) == 0 && !haveExamples {
ran, ok := runTests(matchString, tests)
if !ran && !haveExamples {
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
return
}
return ok
}
func runTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ran, ok bool) {
ok = true
for _, procs := range cpuList {
runtime.GOMAXPROCS(procs)
ctx := newTestContext(*parallel, newMatcher(matchString, *match, "-test.run"))
@ -811,8 +835,9 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
go func() { <-t.signal }()
})
ok = ok && !t.Failed()
ran = ran || t.ran
}
return
return ran, ok
}
// before runs before all testing.