[testrunner] Support basic TAP output
This change produces a TAP output stream to stdout.
The testrunner still produces a summary.json file. We should fix that
and expect upstream consumers to parse the TAP output.
IN-824 #comment
Change-Id: I2e3f5bf590e3149b180a9a5199b7abd6b80c630c
diff --git a/cmd/testrunner/main.go b/cmd/testrunner/main.go
index f4d254c..727d3a1 100644
--- a/cmd/testrunner/main.go
+++ b/cmd/testrunner/main.go
@@ -21,6 +21,7 @@
"fuchsia.googlesource.com/tools/botanist"
"fuchsia.googlesource.com/tools/runtests"
+ "fuchsia.googlesource.com/tools/tap"
"fuchsia.googlesource.com/tools/testrunner"
"fuchsia.googlesource.com/tools/testsharder"
"golang.org/x/crypto/ssh"
@@ -52,6 +53,9 @@
deviceFilepath string
)
+// TestRecorder records the details of test run.
+type TestRecorder func(runtests.TestDetails)
+
func usage() {
fmt.Println(`
testrunner [flags] tests-file
@@ -84,18 +88,40 @@
log.Fatal("-output is required")
}
+ // Load tests.
testsPath := flag.Arg(0)
tests, err := testrunner.LoadTests(testsPath)
if err != nil {
log.Fatalf("failed to load tests from %q: %v", testsPath, err)
}
- if err := execute(tests); err != nil {
+ // Prepare outputs.
+ tapp := tap.NewProducer(os.Stdout)
+ tapp.Plan(len(tests))
+ var summary runtests.TestSummary
+ recordDetails := func(details runtests.TestDetails) {
+ tapp.Ok(details.Result == runtests.TestSuccess, details.Name)
+ summary.Tests = append(summary.Tests, details)
+ }
+
+ // Execute.
+ if err := execute(tests, recordDetails); err != nil {
+ log.Fatal(err)
+ }
+
+ // Write Summary.
+ file, err := os.Create(path.Join(outputDir, "summary.json"))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ encoder := json.NewEncoder(file)
+ if err := encoder.Encode(summary); err != nil {
log.Fatal(err)
}
}
-func execute(tests []testsharder.Test) error {
+func execute(tests []testsharder.Test, recorder TestRecorder) error {
// Validate inputs.
nodename := os.Getenv("NODENAME")
if nodename == "" {
@@ -135,38 +161,25 @@
return fmt.Errorf("could not determine the runtime system for following tests %v", unknownTests)
}
- var summary runtests.TestSummary
-
// Execute UNIX tests locally, assuming we're running in a UNIX environment.
var localTests []testsharder.Test
localTests = append(localTests, groups["linux"]...)
localTests = append(localTests, groups["mac"]...)
if len(localTests) > 0 {
- details, err := runTests(localTests, RunTestInSubprocess, outputDir)
- if err != nil {
+ if err := runTests(localTests, RunTestInSubprocess, outputDir, recorder); err != nil {
return err
}
- summary.Tests = append(summary.Tests, details...)
}
// Execute Fuchsia tests.
if fuchsiaTests, ok := groups["fuchsia"]; ok {
// TODO(IN-824): Record log_listener output.
- details, err := runTests(fuchsiaTests, fuchsiaTester.Test, outputDir)
- if err != nil {
+ if err := runTests(fuchsiaTests, fuchsiaTester.Test, outputDir, recorder); err != nil {
return err
}
- summary.Tests = append(summary.Tests, details...)
}
- summaryFile, err := os.Create(path.Join(outputDir, "summary.json"))
- if err != nil {
- return err
- }
-
- // Log summary to `outputDir`.
- encoder := json.NewEncoder(summaryFile)
- return encoder.Encode(summary)
+ return nil
}
// groupTests splits a list of tests into named subgroups according to the names returned
@@ -211,8 +224,7 @@
return botanist.SSHIntoNode(context.Background(), nodename, config)
}
-func runTests(tests []testsharder.Test, tester Tester, outputDir string) ([]runtests.TestDetails, error) {
- var output []runtests.TestDetails
+func runTests(tests []testsharder.Test, tester Tester, outputDir string, record TestRecorder) error {
for _, test := range tests {
details, err := runTest(context.Background(), test, tester, outputDir)
if err != nil {
@@ -220,11 +232,11 @@
}
if details != nil {
- output = append(output, *details)
+ record(*details)
}
}
- return output, nil
+ return nil
}
func runTest(ctx context.Context, test testsharder.Test, tester Tester, outputDir string) (*runtests.TestDetails, error) {
diff --git a/go.mod b/go.mod
index 48997a7..cd44254 100644
--- a/go.mod
+++ b/go.mod
@@ -8,6 +8,7 @@
github.com/googleapis/gax-go v2.0.2+incompatible // indirect
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 // indirect
github.com/kr/fs v0.1.0 // indirect
+ github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b
github.com/pkg/errors v0.8.1 // indirect
github.com/pkg/sftp v1.8.3
go.chromium.org/luci v0.0.0-20181218015242-20acb618582d
diff --git a/go.sum b/go.sum
index 49189fa..0490d22 100644
--- a/go.sum
+++ b/go.sum
@@ -23,6 +23,8 @@
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b h1:ioAf++SXYsNBCJQdUQYpKsGUFUGvbxHaXFEnonuitI8=
+github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=