forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
junitreport.go
167 lines (137 loc) · 5.15 KB
/
junitreport.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package main
import (
"flag"
"fmt"
"io"
"os"
"strings"
"github.com/openshift/origin/tools/junitreport/pkg/cmd"
)
var (
// parserType is a flag that holds the type of parser to use
parserType string
// builderType is a flag that holds the type of builder to use
builderType string
// rootSuites is a flag that holds the comma-delimited list of root suite names
rootSuites string
// testOutputFile is a flag that holds the path to the file containing test output
testOutputFile string
// outputFile is a flag that holds the path to the jUnit XML report to be written
outputFile string
// stream is a flag that determines if a streamed subset of the input stream should be printed as it is read
stream bool
)
const (
defaultParserType = "gotest"
defaultBuilderType = "flat"
defaultTestOutputFile = "/dev/stdin"
defaultOutputFile = "/dev/stdout"
defaultFilter = false
)
func init() {
flag.StringVar(&parserType, "type", defaultParserType, "which type of test output to parse")
flag.StringVar(&builderType, "suites", defaultBuilderType, "which test suite structure to use")
flag.StringVar(&rootSuites, "roots", "", "comma-delimited list of root suite names")
flag.StringVar(&testOutputFile, "f", defaultTestOutputFile, "the path to the file containing test output to consume")
flag.StringVar(&outputFile, "output", defaultOutputFile, "the path to the jUnit XML output file to write")
flag.BoolVar(&stream, "stream", defaultFilter, "print a streamed subset of the input as it is read")
}
const (
junitReportUsageLong = `Consume test output to create jUnit XML files and summarize jUnit XML files.
%[1]s consumes test output through Stdin and creates jUnit XML files. Currently, only the output of 'go test'
and the output of 'oscmd' functions with $JUNIT_REPORT_OUTPUT set are supported. jUnit XML can be build with
nested or flat test suites. Sub-trees of test suites can be selected when using the nested test-suites represen-
tation to only build XML for some subset of the test output. This parser is greedy, so all output not directly
related to a test suite is considered test case output.
`
junitReportUsage = `Usage:
%[1]s [--type=TEST-OUTPUT-TYPE] [--suites=SUITE-TYPE] [-f=FILE]
%[1]s [-f=FILE] summarize
`
junitReportExamples = `Examples:
# Consume 'go test' output to create a jUnit XML file
go test -v -cover ./... | %[1]s > report.xml
# Consume 'go test' output to create a jUnit XML file, while also printing package output as it is generated
go test -v -cover ./... | %[1]s --stream > report.xml
# Consume 'go test' output from a file to create a jUnit XML file
%[1]s -f testoutput.txt > report.xml
# Consume 'go test' output to create a specific jUnit XML file
%[1]s --output report.xml
# Consume 'go test' output to create a jUnit XML file with nested test suites
go test -v -cover ./... | junitreport --suites=nested > report.xml
# Consume 'go test' output to create a jUnit XML file with nested test suites rooted at 'github.com/maintainer'
go test -v -cover ./... | junitreport --suites=nested --roots=github.com/maintainer > report.xml
# Describe failures and skipped tests in an existing jUnit XML file
cat report.xml | %[1]s summarize
# Consume 'os::cmd' output from to create a jUnit XML file
JUNIT_REPORT='true' hack/test-cmd.sh | junitreport --type=os::cmd > report.xml
`
)
func main() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, junitReportUsageLong+"\n", os.Args[0])
fmt.Fprintf(os.Stderr, junitReportUsage+"\n", os.Args[0])
fmt.Fprintf(os.Stderr, junitReportExamples+"\n", os.Args[0])
fmt.Fprintln(os.Stderr, "Options:")
flag.PrintDefaults()
os.Exit(2)
}
flag.Parse()
var rootSuiteNames []string
if len(rootSuites) > 0 {
rootSuiteNames = strings.Split(rootSuites, ",")
}
var input io.Reader
if testOutputFile == defaultTestOutputFile {
input = os.Stdin
} else {
file, err := os.Open(testOutputFile)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading input file: %v\n", err)
}
defer file.Close()
input = file
}
arguments := flag.Args()
// If we are asked to summarize an XML file, that is all we do
if len(arguments) == 1 && arguments[0] == "summarize" {
summary, err := cmd.Summarize(input)
if err != nil {
fmt.Fprintf(os.Stderr, "Error summarizing jUnit XML file: %v\n", err)
os.Exit(1)
}
fmt.Fprint(os.Stdout, summary)
os.Exit(0)
}
if len(arguments) > 1 {
fmt.Fprintf(os.Stderr, "Incorrect usage of %[1]s, see '%[1]s --help' for more details.\n", os.Args[0])
os.Exit(1)
}
var output io.Writer
if outputFile == defaultOutputFile {
output = os.Stdout
} else {
file, err := os.Create(outputFile)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating output file: %v\n", err)
}
defer file.Close()
output = file
}
// Otherwise, we get ready to parse and generate XML output.
options := cmd.JUnitReportOptions{
Stream: stream,
Input: input,
Output: output,
}
err := options.Complete(builderType, parserType, rootSuiteNames)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing flags: %v\n", err)
os.Exit(1)
}
err = options.Run()
if err != nil {
fmt.Fprintf(os.Stderr, "Error generating output: %v\n", err)
os.Exit(1)
}
}