Browse code

enabled junitreport tool to stream output

Steve Kuznetsov authored on 2016/02/29 23:53:22
Showing 6 changed files
... ...
@@ -214,14 +214,26 @@ if [[ -n "${junit_report}" ]]; then
214 214
     test_output_file="${LOG_DIR}/test-go.log"
215 215
     junit_report_file="${ARTIFACT_DIR}/report.xml"
216 216
 
217
-    # we don't care if 'go test' fails, we want to summarize the output anyway.
218
-    return_code=0 # default to 0, overwrite only if the following line fails
219
-    go test ${gotest_flags} ${test_packages} > ${test_output_file} 2>&1 || return_code=$?
220
-    echo "[INFO] Output from \`go test\` redirected to ${test_output_file}"
221
-
222
-    cat "${test_output_file}" | "${junitreport}" --type gotest --suites nested --roots github.com/openshift/origin > "${junit_report_file}"
223
-    echo "[INFO] jUnit XML report placed at ${junit_report_file}"
217
+    echo "[INFO] Running \`go test\`..."
218
+    # we don't care if the `go test` fails in this pipe, as we want to generate the report and summarize the output anyway
219
+    set +o pipefail
220
+
221
+    go test ${gotest_flags} ${test_packages} 2>&1              \
222
+        | tee ${test_output_file}                              \
223
+        | "${junitreport}" --type gotest                       \
224
+                           --suites nested                     \
225
+                           --roots github.com/openshift/origin \
226
+                           --stream                            \
227
+                           --output "${junit_report_file}"
228
+
229
+    return_code="${PIPESTATUS[0]}"
230
+    set -o pipefail
231
+    
232
+    echo
224 233
     cat "${junit_report_file}" | "${junitreport}" summarize
234
+    echo "[INFO] Full output from \`go test\` logged at ${test_output_file}"
235
+    echo "[INFO] jUnit XML report placed at ${junit_report_file}"
236
+
225 237
     exit "${return_code}"
226 238
 
227 239
 elif [[ -n "${coverage_output_dir}" ]]; then
... ...
@@ -22,12 +22,20 @@ var (
22 22
 
23 23
 	// testOutputFile is a flag that holds the path to the file containing test output
24 24
 	testOutputFile string
25
+
26
+	// outputFile is a flag that holds the path to the jUnit XML report to be written
27
+	outputFile string
28
+
29
+	// stream is a flag that determines if a streamed subset of the input stream should be printed as it is read
30
+	stream bool
25 31
 )
26 32
 
27 33
 const (
28 34
 	defaultParserType     = "gotest"
29 35
 	defaultBuilderType    = "flat"
30 36
 	defaultTestOutputFile = "/dev/stdin"
37
+	defaultOutputFile     = "/dev/stdout"
38
+	defaultFilter         = false
31 39
 )
32 40
 
33 41
 func init() {
... ...
@@ -35,6 +43,8 @@ func init() {
35 35
 	flag.StringVar(&builderType, "suites", defaultBuilderType, "which test suite structure to use")
36 36
 	flag.StringVar(&rootSuites, "roots", "", "comma-delimited list of root suite names")
37 37
 	flag.StringVar(&testOutputFile, "f", defaultTestOutputFile, "the path to the file containing test output to consume")
38
+	flag.StringVar(&outputFile, "output", defaultOutputFile, "the path to the jUnit XML output file to write")
39
+	flag.BoolVar(&stream, "stream", defaultFilter, "print a streamed subset of the input as it is read")
38 40
 }
39 41
 
40 42
 const (
... ...
@@ -55,9 +65,15 @@ parser is greedy, so all output not directly related to a test suite is consider
55 55
   # Consume 'go test' output to create a jUnit XML file
56 56
   $ go test -v -cover ./... | %[1]s > report.xml
57 57
 
58
+  # Consume 'go test' output to create a jUnit XML file, while also printing package output as it is generated
59
+  $ go test -v -cover ./... | %[1]s --stream > report.xml
60
+
58 61
   # Consume 'go test' output from a file to create a jUnit XML file
59 62
   $ %[1]s -f testoutput.txt > report.xml
60 63
 
64
+  # Consume 'go test' output to create a specific jUnit XML file
65
+  $ %[1]s --output report.xml
66
+
61 67
   # Consume 'go test' output to create a jUnit XML file with nested test suites
62 68
   $ go test -v -cover ./... | junitreport --suites=nested > report.xml
63 69
 
... ...
@@ -114,10 +130,23 @@ func main() {
114 114
 		os.Exit(1)
115 115
 	}
116 116
 
117
+	var output io.Writer
118
+	if outputFile == defaultOutputFile {
119
+		output = os.Stdout
120
+	} else {
121
+		file, err := os.Create(outputFile)
122
+		if err != nil {
123
+			fmt.Fprintf(os.Stderr, "Error creating output file: %v\n", err)
124
+		}
125
+		defer file.Close()
126
+		output = file
127
+	}
128
+
117 129
 	// Otherwise, we get ready to parse and generate XML output.
118 130
 	options := cmd.JUnitReportOptions{
131
+		Stream: stream,
119 132
 		Input:  input,
120
-		Output: os.Stdout,
133
+		Output: output,
121 134
 	}
122 135
 
123 136
 	err := options.Complete(builderType, parserType, rootSuiteNames)
... ...
@@ -42,6 +42,9 @@ type JUnitReportOptions struct {
42 42
 	// ParserType is the parser type that will be used to parse test output
43 43
 	ParserType testParserType
44 44
 
45
+	// Stream determines if package result lines should be printed to the output as they are found
46
+	Stream bool
47
+
45 48
 	// Input is the reader for the test output to be parsed
46 49
 	Input io.Reader
47 50
 
... ...
@@ -83,7 +86,7 @@ func (o *JUnitReportOptions) Run() error {
83 83
 	var testParser parser.TestOutputParser
84 84
 	switch o.ParserType {
85 85
 	case goTestParserType:
86
-		testParser = gotest.NewParser(builder)
86
+		testParser = gotest.NewParser(builder, o.Stream)
87 87
 	}
88 88
 
89 89
 	testSuites, err := testParser.Parse(bufio.NewScanner(o.Input))
... ...
@@ -2,6 +2,8 @@ package gotest
2 2
 
3 3
 import (
4 4
 	"bufio"
5
+	"fmt"
6
+	"os"
5 7
 	"strings"
6 8
 
7 9
 	"github.com/openshift/origin/tools/junitreport/pkg/api"
... ...
@@ -10,11 +12,12 @@ import (
10 10
 )
11 11
 
12 12
 // NewParser returns a new parser that's capable of parsing Go unit test output
13
-func NewParser(builder builder.TestSuitesBuilder) parser.TestOutputParser {
13
+func NewParser(builder builder.TestSuitesBuilder, stream bool) parser.TestOutputParser {
14 14
 	return &testOutputParser{
15 15
 		builder:     builder,
16 16
 		testParser:  newTestDataParser(),
17 17
 		suiteParser: newTestSuiteDataParser(),
18
+		stream:      stream,
18 19
 	}
19 20
 }
20 21
 
... ...
@@ -22,6 +25,7 @@ type testOutputParser struct {
22 22
 	builder     builder.TestSuitesBuilder
23 23
 	testParser  testDataParser
24 24
 	suiteParser testSuiteDataParser
25
+	stream      bool
25 26
 }
26 27
 
27 28
 // Parse parses `go test -v` output into test suites. Test output from `go test -v` is not bookmarked for packages, so
... ...
@@ -89,6 +93,10 @@ func (p *testOutputParser) Parse(input *bufio.Scanner) (*api.TestSuites, error)
89 89
 		}
90 90
 
91 91
 		if p.suiteParser.MarksCompletion(line) {
92
+			if p.stream {
93
+				fmt.Fprintln(os.Stdout, line)
94
+			}
95
+
92 96
 			p.builder.AddSuite(currentSuite)
93 97
 
94 98
 			currentSuite = &api.TestSuite{}
... ...
@@ -376,7 +376,7 @@ PASS`,
376 376
 	}
377 377
 
378 378
 	for _, testCase := range testCases {
379
-		parser := NewParser(flat.NewTestSuitesBuilder())
379
+		parser := NewParser(flat.NewTestSuitesBuilder(), false)
380 380
 
381 381
 		testFile := "./../../../test/gotest/testdata/" + testCase.testFile
382 382
 
... ...
@@ -496,7 +496,7 @@ PASS`, // we include this line greedily even though it does not belong to the te
496 496
 	}
497 497
 
498 498
 	for _, testCase := range testCases {
499
-		parser := NewParser(nested.NewTestSuitesBuilder(testCase.rootSuiteNames))
499
+		parser := NewParser(nested.NewTestSuitesBuilder(testCase.rootSuiteNames), false)
500 500
 
501 501
 		testFile := "./../../../test/gotest/testdata/" + testCase.testFile
502 502