Skip to content

Commit 940046d

Browse files
joschijkz-stripe
andauthored
feat: add AssumeNoBuildOutput option to ignore build output (#11)
* Add AssumeNoBuildOutput option We use the go-junit-report libraries in a context where we know that the build has already completed. As such some tests have been written that produce output that looks like build output, but is not. This option allows the parser to work in this context. * Expose AssumeNoBuildOutput via assume-no-build-output flag --------- Co-authored-by: Josh Kunz <jkz@stripe.com>
1 parent 09c6e99 commit 940046d

File tree

4 files changed

+79
-27
lines changed

4 files changed

+79
-27
lines changed

internal/gojunitreport/go-junit-report.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ type parser interface {
2020

2121
// Config contains the go-junit-report command configuration.
2222
type Config struct {
23-
Parser string
24-
Hostname string
25-
PackageName string
26-
SkipXMLHeader bool
27-
SubtestMode gotest.SubtestMode
28-
Properties map[string]string
29-
TimestampFunc func() time.Time
23+
Parser string
24+
Hostname string
25+
PackageName string
26+
SkipXMLHeader bool
27+
SubtestMode gotest.SubtestMode
28+
Properties map[string]string
29+
TimestampFunc func() time.Time
30+
AssumeNoBuildOutput bool
3031

3132
// For debugging
3233
PrintEvents bool
@@ -86,5 +87,6 @@ func (c Config) gotestOptions() []gotest.Option {
8687
gotest.PackageName(c.PackageName),
8788
gotest.SetSubtestMode(c.SubtestMode),
8889
gotest.TimestampFunc(c.TimestampFunc),
90+
gotest.AssumeNoBuildOutput(c.AssumeNoBuildOutput),
8991
}
9092
}

main.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@ var (
2222
)
2323

2424
var (
25-
noXMLHeader = flag.Bool("no-xml-header", false, "do not print xml header")
26-
packageName = flag.String("package-name", "", "specify a default package `name` to use if output does not contain a package name")
27-
setExitCode = flag.Bool("set-exit-code", false, "set exit code to 1 if tests failed")
28-
version = flag.Bool("version", false, "print version")
29-
input = flag.String("in", "", "read go test log from `file`")
30-
output = flag.String("out", "", "write XML report to `file`")
31-
iocopy = flag.Bool("iocopy", false, "copy input to stdout; can only be used in conjunction with -out")
32-
properties = make(keyValueFlag)
33-
parser = flag.String("parser", "gotest", "set input parser: gotest, gojson")
34-
mode = flag.String("subtest-mode", "", "set subtest `mode`: ignore-parent-results (subtest parents always pass), exclude-parents (subtest parents are excluded from the report)")
25+
noXMLHeader = flag.Bool("no-xml-header", false, "do not print xml header")
26+
packageName = flag.String("package-name", "", "specify a default package `name` to use if output does not contain a package name")
27+
setExitCode = flag.Bool("set-exit-code", false, "set exit code to 1 if tests failed")
28+
version = flag.Bool("version", false, "print version")
29+
input = flag.String("in", "", "read go test log from `file`")
30+
output = flag.String("out", "", "write XML report to `file`")
31+
iocopy = flag.Bool("iocopy", false, "copy input to stdout; can only be used in conjunction with -out")
32+
properties = make(keyValueFlag)
33+
parser = flag.String("parser", "gotest", "set input parser: gotest, gojson")
34+
mode = flag.String("subtest-mode", "", "set subtest `mode`: ignore-parent-results (subtest parents always pass), exclude-parents (subtest parents are excluded from the report)")
35+
assumeNoBuildOutput = flag.Bool("assume-no-build-output", false, "assume the input contains no build output and everything is test output")
3536

3637
// debug flags
3738
printEvents = flag.Bool("debug.print-events", false, "print events generated by the go test parser")
@@ -100,13 +101,14 @@ func main() {
100101
hostname, _ := os.Hostname() // ignore error
101102

102103
config := gojunitreport.Config{
103-
Parser: *parser,
104-
Hostname: hostname,
105-
PackageName: *packageName,
106-
SkipXMLHeader: *noXMLHeader,
107-
SubtestMode: subtestMode,
108-
Properties: properties,
109-
PrintEvents: *printEvents,
104+
Parser: *parser,
105+
Hostname: hostname,
106+
PackageName: *packageName,
107+
SkipXMLHeader: *noXMLHeader,
108+
SubtestMode: subtestMode,
109+
Properties: properties,
110+
PrintEvents: *printEvents,
111+
AssumeNoBuildOutput: *assumeNoBuildOutput,
110112
}
111113
report, err := config.Run(in, out)
112114
if err != nil {

parser/gotest/gotest.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,21 @@ func SetSubtestMode(mode SubtestMode) Option {
109109
}
110110
}
111111

112+
// AssumeNoBuildOutput is an Option disables "build_output" event parsing. This
113+
// option is most useful when running tests that are known to build correctly,
114+
// or have already been built (e.g. via go test -c, or an alternative build
115+
// system).
116+
func AssumeNoBuildOutput(assumeNoBuildOutput bool) Option {
117+
return func(p *Parser) {
118+
p.assumeNoBuildOutput = assumeNoBuildOutput
119+
}
120+
}
121+
112122
// Parser is a Go test output Parser.
113123
type Parser struct {
114-
packageName string
115-
subtestMode SubtestMode
124+
packageName string
125+
subtestMode SubtestMode
126+
assumeNoBuildOutput bool
116127

117128
timestampFunc func() time.Time
118129

@@ -208,7 +219,7 @@ func (p *Parser) parseLine(line string) (events []Event) {
208219
return p.benchSummary(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6])
209220
} else if matches := regexEndBenchmark.FindStringSubmatch(line); len(matches) == 3 {
210221
return p.endBench(matches[1], matches[2])
211-
} else if strings.HasPrefix(line, "# ") {
222+
} else if !p.assumeNoBuildOutput && strings.HasPrefix(line, "# ") {
212223
fields := strings.Fields(strings.TrimPrefix(line, "# "))
213224
if len(fields) == 1 || len(fields) == 2 {
214225
return p.buildOutput(fields[0])

parser/gotest/gotest_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,40 @@ func TestParseLine(t *testing.T) {
225225
})
226226
}
227227
}
228+
229+
func TestParseLine_AssumeNoBuildOutput(t *testing.T) {
230+
tests := []parseLineTest{
231+
{
232+
"# package/name/failing1",
233+
[]Event{{Type: "output", Data: "# package/name/failing1"}},
234+
},
235+
{
236+
"# package/name/failing2 [package/name/failing2.test]",
237+
[]Event{{Type: "output", Data: "# package/name/failing2 [package/name/failing2.test]"}},
238+
},
239+
}
240+
241+
// Include all the other tests that don't produce build_output as well, they
242+
// should continue functioning normally.
243+
Outer:
244+
for _, test := range parseLineTests {
245+
for _, event := range test.events {
246+
if event.Type == "build_output" {
247+
continue Outer
248+
}
249+
}
250+
251+
tests = append(tests, test)
252+
}
253+
254+
for i, test := range tests {
255+
name := fmt.Sprintf("%d-%s", i, test.Name())
256+
t.Run(name, func(t *testing.T) {
257+
parser := NewParser(AssumeNoBuildOutput(true))
258+
events := parser.parseLine(test.input)
259+
if diff := cmp.Diff(test.events, events); diff != "" {
260+
t.Errorf("parseLine(%q) returned unexpected events, diff (-want, +got):\n%v", test.input, diff)
261+
}
262+
})
263+
}
264+
}

0 commit comments

Comments
 (0)