diff options
-rw-r--r-- | main.go | 18 | ||||
-rw-r--r-- | main_test.go | 1 | ||||
-rw-r--r-- | src/testing/testing.go | 78 | ||||
-rw-r--r-- | testdata/testing.go | 42 | ||||
-rw-r--r-- | testdata/testing.txt | 16 |
5 files changed, 133 insertions, 22 deletions
@@ -158,7 +158,7 @@ func Build(pkgName, outpath string, options *compileopts.Options) error { // Test runs the tests in the given package. Returns whether the test passed and // possibly an error if the test failed to run. -func Test(pkgName string, options *compileopts.Options, testCompileOnly bool, outpath string) (bool, error) { +func Test(pkgName string, options *compileopts.Options, testCompileOnly, testVerbose bool, outpath string) (bool, error) { options.TestConfig.CompileTestBinary = true config, err := builder.NewConfig(options) if err != nil { @@ -184,7 +184,7 @@ func Test(pkgName string, options *compileopts.Options, testCompileOnly bool, ou // Run the test. start := time.Now() var err error - passed, err = runPackageTest(config, result) + passed, err = runPackageTest(config, result, testVerbose) if err != nil { return err } @@ -210,10 +210,14 @@ func Test(pkgName string, options *compileopts.Options, testCompileOnly bool, ou // runPackageTest runs a test binary that was previously built. The return // values are whether the test passed and any errors encountered while trying to // run the binary. -func runPackageTest(config *compileopts.Config, result builder.BuildResult) (bool, error) { +func runPackageTest(config *compileopts.Config, result builder.BuildResult, testVerbose bool) (bool, error) { if len(config.Target.Emulator) == 0 { // Run directly. - cmd := executeCommand(config.Options, result.Binary) + var flags []string + if testVerbose { + flags = append(flags, "-test.v") + } + cmd := executeCommand(config.Options, result.Binary, flags...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = result.MainDir @@ -229,6 +233,7 @@ func runPackageTest(config *compileopts.Config, result builder.BuildResult) (boo return true, nil } else { // Run in an emulator. + // TODO: pass the -test.v flag if needed. args := append(config.Target.Emulator[1:], result.Binary) cmd := executeCommand(config.Options, config.Target.Emulator[0], args...) buf := &bytes.Buffer{} @@ -1038,9 +1043,10 @@ func main() { if command == "help" || command == "build" || command == "build-library" || command == "test" { flag.StringVar(&outpath, "o", "", "output filename") } - var testCompileOnlyFlag *bool + var testCompileOnlyFlag, testVerboseFlag *bool if command == "help" || command == "test" { testCompileOnlyFlag = flag.Bool("c", false, "compile the test binary but do not run it") + testVerboseFlag = flag.Bool("v", false, "verbose: print additional output") } // Early command processing, before commands are interpreted by the Go flag @@ -1201,7 +1207,7 @@ func main() { allTestsPassed := true for _, pkgName := range pkgNames { // TODO: parallelize building the test binaries - passed, err := Test(pkgName, options, *testCompileOnlyFlag, outpath) + passed, err := Test(pkgName, options, *testCompileOnlyFlag, *testVerboseFlag, outpath) handleCompilerError(err) if !passed { allTestsPassed = false diff --git a/main_test.go b/main_test.go index a502115e4..f47b43398 100644 --- a/main_test.go +++ b/main_test.go @@ -51,6 +51,7 @@ func TestCompiler(t *testing.T) { "stdlib.go", "string.go", "structs.go", + "testing.go", "zeroalloc.go", } diff --git a/src/testing/testing.go b/src/testing/testing.go index 88e751ffb..c15ddab53 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -10,15 +10,34 @@ package testing import ( "bytes" + "flag" "fmt" - "io" "os" + "strings" ) +// Testing flags. +var ( + flagVerbose bool +) + +var initRan bool + +// Init registers testing flags. It has no effect if it has already run. +func Init() { + if initRan { + return + } + initRan = true + + flag.BoolVar(&flagVerbose, "test.v", false, "verbose: print additional output") +} + // common holds the elements common between T and B and // captures common methods such as Errorf. type common struct { - output io.Writer + output bytes.Buffer + indent string failed bool // Test or benchmark has failed. skipped bool // Test of benchmark has been skipped. @@ -53,7 +72,6 @@ var _ TB = (*B)(nil) // type T struct { common - indent string } // Name returns the name of the running test or benchmark. @@ -85,8 +103,22 @@ func (c *common) FailNow() { // log generates the output. func (c *common) log(s string) { // This doesn't print the same as in upstream go, but works for now. - fmt.Fprintf(c.output, "\t") - fmt.Fprintln(c.output, s) + if len(s) != 0 && s[len(s)-1] == '\n' { + s = s[:len(s)-1] + } + lines := strings.Split(s, "\n") + // First line. + c.output.WriteString(c.indent) + c.output.WriteString(" ") // 4 spaces + c.output.WriteString(lines[0]) + c.output.WriteByte('\n') + // More lines. + for _, line := range lines[1:] { + c.output.WriteString(c.indent) + c.output.WriteString(" ") // 8 spaces + c.output.WriteString(line) + c.output.WriteByte('\n') + } } // Log formats its arguments using default formatting, analogous to Println, @@ -165,25 +197,30 @@ func (c *common) Helper() { func (t *T) Run(name string, f func(t *T)) bool { // Create a subtest. sub := T{ - indent: t.indent + " ", common: common{ name: t.name + "/" + name, - output: &bytes.Buffer{}, + indent: t.indent + " ", }, } // Run the test. - fmt.Printf("=== RUN %s\n", sub.name) + if flagVerbose { + fmt.Fprintf(&t.output, "=== RUN %s\n", sub.name) + + } f(&sub) // Process the result (pass or fail). if sub.failed { t.failed = true - fmt.Printf(sub.indent+"--- FAIL: %s\n", sub.name) + fmt.Fprintf(&t.output, sub.indent+"--- FAIL: %s\n", sub.name) + t.output.Write(sub.output.Bytes()) } else { - fmt.Printf(sub.indent+"--- PASS: %s\n", sub.name) + if flagVerbose { + fmt.Fprintf(&t.output, sub.indent+"--- PASS: %s\n", sub.name) + t.output.Write(sub.output.Bytes()) + } } - fmt.Print(sub.output) return !sub.failed } @@ -205,24 +242,32 @@ func (m *M) Run() int { fmt.Fprintln(os.Stderr, "testing: warning: no tests to run") } + if !flag.Parsed() { + flag.Parse() + } + failures := 0 for _, test := range m.Tests { t := &T{ common: common{ - name: test.Name, - output: &bytes.Buffer{}, + name: test.Name, }, } - fmt.Printf("=== RUN %s\n", test.Name) + if flagVerbose { + fmt.Printf("=== RUN %s\n", test.Name) + } test.F(t) if t.failed { fmt.Printf("--- FAIL: %s\n", test.Name) + os.Stdout.Write(t.output.Bytes()) } else { - fmt.Printf("--- PASS: %s\n", test.Name) + if flagVerbose { + fmt.Printf("--- PASS: %s\n", test.Name) + os.Stdout.Write(t.output.Bytes()) + } } - fmt.Print(t.output) if t.failed { failures++ @@ -242,6 +287,7 @@ func TestMain(m *M) { } func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M { + Init() return &M{ Tests: tests, } diff --git a/testdata/testing.go b/testdata/testing.go new file mode 100644 index 000000000..ba952f34d --- /dev/null +++ b/testdata/testing.go @@ -0,0 +1,42 @@ +package main + +// TODO: also test the verbose version. + +import ( + "testing" +) + +func TestFoo(t *testing.T) { + t.Log("log Foo.a") + t.Log("log Foo.b") +} + +func TestBar(t *testing.T) { + t.Log("log Bar") + t.Log("log g\nh\ni\n") + t.Run("Bar1", func(t *testing.T) {}) + t.Run("Bar2", func(t *testing.T) { + t.Log("log Bar2\na\nb\nc") + t.Error("failed") + t.Log("after failed") + }) + t.Run("Bar3", func(t *testing.T) {}) + t.Log("log Bar end") +} + +var tests = []testing.InternalTest{ + {"TestFoo", TestFoo}, + {"TestBar", TestBar}, +} + +var benchmarks = []testing.InternalBenchmark{} + +var examples = []testing.InternalExample{} + +func main() { + m := testing.MainStart(nil, tests, benchmarks, examples) + exitcode := m.Run() + if exitcode != 0 { + println("exitcode:", exitcode) + } +} diff --git a/testdata/testing.txt b/testdata/testing.txt new file mode 100644 index 000000000..816246c2e --- /dev/null +++ b/testdata/testing.txt @@ -0,0 +1,16 @@ +--- FAIL: TestBar + log Bar + log g + h + i + + --- FAIL: TestBar/Bar2 + log Bar2 + a + b + c + failed + after failed + log Bar end +FAIL +exitcode: 1 |