testing.go: hoist runTests() out of Run() to match upstream a bit better
Only trivial functional changes: - gets rid of mistaken extra "no tests" warning (whoops) - matches upstream's exit code better In preparation for switching to fancy test filtering.
Этот коммит содержится в:
родитель
daf5d0b63a
коммит
610a20c4d5
1 изменённых файлов: 38 добавлений и 28 удалений
|
@ -47,6 +47,7 @@ type common struct {
|
||||||
output bytes.Buffer
|
output bytes.Buffer
|
||||||
w io.Writer // either &output, or at top level, os.Stdout
|
w io.Writer // either &output, or at top level, os.Stdout
|
||||||
indent string
|
indent string
|
||||||
|
ran bool // Test or benchmark (or one of its subtests) was executed.
|
||||||
failed bool // Test or benchmark has failed.
|
failed bool // Test or benchmark has failed.
|
||||||
skipped bool // Test of benchmark has been skipped.
|
skipped bool // Test of benchmark has been skipped.
|
||||||
cleanups []func() // optional functions to be called at the end of the test
|
cleanups []func() // optional functions to be called at the end of the test
|
||||||
|
@ -278,6 +279,7 @@ func tRunner(t *T, fn func(t *T)) {
|
||||||
t.duration += time.Since(t.start) // TODO: capture cleanup time, too.
|
t.duration += time.Since(t.start) // TODO: capture cleanup time, too.
|
||||||
|
|
||||||
t.report() // Report after all subtests have finished.
|
t.report() // Report after all subtests have finished.
|
||||||
|
t.ran = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run runs f as a subtest of t called name. It waits until the subtest is finished
|
// Run runs f as a subtest of t called name. It waits until the subtest is finished
|
||||||
|
@ -304,6 +306,10 @@ type M struct {
|
||||||
Benchmarks []InternalBenchmark
|
Benchmarks []InternalBenchmark
|
||||||
|
|
||||||
deps testDeps
|
deps testDeps
|
||||||
|
|
||||||
|
// value to pass to os.Exit, the outer test func main
|
||||||
|
// harness calls os.Exit with this code. See #34129.
|
||||||
|
exitCode int
|
||||||
}
|
}
|
||||||
|
|
||||||
type testDeps interface {
|
type testDeps interface {
|
||||||
|
@ -319,39 +325,55 @@ func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the test suite.
|
// Run runs the tests. It returns an exit code to pass to os.Exit.
|
||||||
func (m *M) Run() int {
|
func (m *M) Run() (code int) {
|
||||||
|
defer func() {
|
||||||
|
code = m.exitCode
|
||||||
|
}()
|
||||||
|
|
||||||
if !flag.Parsed() {
|
if !flag.Parsed() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
failures := 0
|
testRan, testOk := runTests(m.deps.MatchString, m.Tests)
|
||||||
|
if !testRan && *matchBenchmarks == "" {
|
||||||
|
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
|
||||||
|
}
|
||||||
|
if !testOk || !runBenchmarks(m.deps.MatchString, m.Benchmarks) {
|
||||||
|
fmt.Println("FAIL")
|
||||||
|
m.exitCode = 1
|
||||||
|
} else {
|
||||||
|
if flagVerbose {
|
||||||
|
fmt.Println("PASS")
|
||||||
|
}
|
||||||
|
m.exitCode = 0
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ran, ok bool) {
|
||||||
|
ok = true
|
||||||
if flagRunRegexp != "" {
|
if flagRunRegexp != "" {
|
||||||
var filtered []InternalTest
|
var filtered []InternalTest
|
||||||
|
|
||||||
// pre-test the regexp; we don't want to bother logging one failure for every test name if the regexp is broken
|
// pre-test the regexp; we don't want to bother logging one failure for every test name if the regexp is broken
|
||||||
if _, err := m.deps.MatchString(flagRunRegexp, "some-test-name"); err != nil {
|
if _, err := matchString(flagRunRegexp, "some-test-name"); err != nil {
|
||||||
fmt.Println("testing: invalid regexp for -test.run:", err.Error())
|
fmt.Println("testing: invalid regexp for -test.run:", err.Error())
|
||||||
failures++
|
return false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter the list of tests before we try to run them
|
// filter the list of tests before we try to run them
|
||||||
for _, test := range m.Tests {
|
for _, test := range tests {
|
||||||
// ignore the error; we already tested that the regexp compiles fine above
|
// ignore the error; we already tested that the regexp compiles fine above
|
||||||
if match, _ := m.deps.MatchString(flagRunRegexp, test.Name); match {
|
if match, _ := matchString(flagRunRegexp, test.Name); match {
|
||||||
filtered = append(filtered, test)
|
filtered = append(filtered, test)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Tests = filtered
|
tests = filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.Tests) == 0 && len(m.Benchmarks) == 0 {
|
for _, test := range tests {
|
||||||
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range m.Tests {
|
|
||||||
t := &T{
|
t := &T{
|
||||||
common: common{
|
common: common{
|
||||||
name: test.Name,
|
name: test.Name,
|
||||||
|
@ -361,22 +383,10 @@ func (m *M) Run() int {
|
||||||
|
|
||||||
tRunner(t, test.F)
|
tRunner(t, test.F)
|
||||||
|
|
||||||
if t.failed {
|
ok = ok && !t.Failed()
|
||||||
failures++
|
ran = ran || t.ran
|
||||||
}
|
}
|
||||||
}
|
return ran, ok
|
||||||
|
|
||||||
if len(m.Tests) == 0 && *matchBenchmarks == "" {
|
|
||||||
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
|
|
||||||
}
|
|
||||||
if failures > 0 || !runBenchmarks(m.deps.MatchString, m.Benchmarks) {
|
|
||||||
fmt.Println("FAIL")
|
|
||||||
} else {
|
|
||||||
if flagVerbose {
|
|
||||||
fmt.Println("PASS")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return failures
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *T) report() {
|
func (t *T) report() {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче