| ... | ... |
@@ -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 |
|