mirror of
https://github.com/jstemmer/go-junit-report.git
synced 2025-04-05 05:00:15 -05:00
gtr, parser/gotest: Add support for build errors
This commit is contained in:
parent
b1b88456c1
commit
ffc33941fa
@ -7,9 +7,10 @@ import (
|
||||
|
||||
// ReportBuilder builds Reports.
|
||||
type ReportBuilder struct {
|
||||
packages []Package
|
||||
tests map[int]Test
|
||||
benchmarks map[int]Benchmark
|
||||
packages []Package
|
||||
tests map[int]Test
|
||||
benchmarks map[int]Benchmark
|
||||
buildErrors map[int]BuildError
|
||||
|
||||
// state
|
||||
nextId int // next free id
|
||||
@ -25,6 +26,7 @@ func NewReportBuilder(packageName string) *ReportBuilder {
|
||||
return &ReportBuilder{
|
||||
tests: make(map[int]Test),
|
||||
benchmarks: make(map[int]Benchmark),
|
||||
buildErrors: make(map[int]BuildError),
|
||||
nextId: 1,
|
||||
packageName: packageName,
|
||||
}
|
||||
@ -76,7 +78,29 @@ func (b *ReportBuilder) Benchmark(name string, iterations int64, nsPerOp, mbPerS
|
||||
}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) CreatePackage(name string, duration time.Duration) {
|
||||
func (b *ReportBuilder) CreateBuildError(packageName string) {
|
||||
b.buildErrors[b.newId()] = BuildError{Name: packageName}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) CreatePackage(name string, duration time.Duration, data string) {
|
||||
// Build errors are treated somewhat differently. Rather than having a
|
||||
// single package with all build errors collected so far, we only care
|
||||
// about the build errors for this particular package.
|
||||
for id, buildErr := range b.buildErrors {
|
||||
if buildErr.Name == name {
|
||||
if len(b.tests) > 0 || len(b.benchmarks) > 0 {
|
||||
panic("unexpected tests and/or benchmarks found in build error package")
|
||||
}
|
||||
buildErr.Cause = data
|
||||
b.packages = append(b.packages, Package{
|
||||
Name: name,
|
||||
BuildError: buildErr,
|
||||
})
|
||||
delete(b.buildErrors, id)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Collect tests and benchmarks for this package, maintaining insertion order.
|
||||
var tests []Test
|
||||
var benchmarks []Benchmark
|
||||
@ -115,9 +139,20 @@ func (b *ReportBuilder) AppendOutput(line string) {
|
||||
b.output = append(b.output, line)
|
||||
return
|
||||
}
|
||||
t := b.tests[b.lastId]
|
||||
t.Output = append(t.Output, line)
|
||||
b.tests[b.lastId] = t
|
||||
|
||||
if t, ok := b.tests[b.lastId]; ok {
|
||||
t.Output = append(t.Output, line)
|
||||
b.tests[b.lastId] = t
|
||||
} else if bm, ok := b.benchmarks[b.lastId]; ok {
|
||||
bm.Output = append(bm.Output, line)
|
||||
b.benchmarks[b.lastId] = bm
|
||||
} else if be, ok := b.buildErrors[b.lastId]; ok {
|
||||
be.Output = append(be.Output, line)
|
||||
b.buildErrors[b.lastId] = be
|
||||
} else {
|
||||
fmt.Printf("DEBUG output else\n")
|
||||
b.output = append(b.output, line)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) findTest(name string) int {
|
||||
|
@ -38,6 +38,8 @@ type Package struct {
|
||||
|
||||
Tests []Test
|
||||
Benchmarks []Benchmark
|
||||
|
||||
BuildError BuildError
|
||||
}
|
||||
|
||||
type Test struct {
|
||||
@ -58,6 +60,12 @@ type Benchmark struct {
|
||||
AllocsPerOp int64
|
||||
}
|
||||
|
||||
type BuildError struct {
|
||||
Name string
|
||||
Cause string
|
||||
Output []string
|
||||
}
|
||||
|
||||
// FromEvents creates a Report from the given list of events.
|
||||
// TODO: make packageName optional option
|
||||
func FromEvents(events []Event, packageName string) Report {
|
||||
@ -72,9 +80,11 @@ func FromEvents(events []Event, packageName string) Report {
|
||||
report.Benchmark(ev.Name, ev.Iterations, ev.NsPerOp, ev.MBPerSec, ev.BytesPerOp, ev.AllocsPerOp)
|
||||
case "status": // ignore for now
|
||||
case "summary":
|
||||
report.CreatePackage(ev.Name, ev.Duration)
|
||||
report.CreatePackage(ev.Name, ev.Duration, ev.Data)
|
||||
case "coverage":
|
||||
report.Coverage(ev.CovPct, ev.CovPackages)
|
||||
case "build_output":
|
||||
report.CreateBuildError(ev.Name)
|
||||
case "output":
|
||||
report.AppendOutput(ev.Data)
|
||||
default:
|
||||
@ -101,6 +111,21 @@ func JUnit(report Report) junit.Testsuites {
|
||||
}
|
||||
}
|
||||
|
||||
// JUnit doesn't have a good way of dealing with build errors, so we
|
||||
// create a single failing test that contains the build error details.
|
||||
if pkg.BuildError.Name != "" {
|
||||
tc := junit.Testcase{
|
||||
Classname: pkg.BuildError.Name,
|
||||
Name: pkg.BuildError.Cause,
|
||||
Time: junit.FormatDuration(0),
|
||||
Failure: &junit.Result{
|
||||
Message: "Failed",
|
||||
Data: strings.Join(pkg.BuildError.Output, "\n"),
|
||||
},
|
||||
}
|
||||
suite.AddTestcase(tc)
|
||||
}
|
||||
|
||||
for _, test := range pkg.Tests {
|
||||
duration += test.Duration
|
||||
|
||||
|
@ -54,6 +54,13 @@ func (p *parser) parseLine(line string) {
|
||||
p.coverage(matches[1], matches[2])
|
||||
} else if matches := regexBenchmark.FindStringSubmatch(line); len(matches) == 7 {
|
||||
p.benchmark(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6])
|
||||
} else if strings.HasPrefix(line, "# ") {
|
||||
fields := strings.Fields(strings.TrimPrefix(line, "# "))
|
||||
if len(fields) == 1 || len(fields) == 2 {
|
||||
p.buildOutput(fields[0])
|
||||
} else {
|
||||
p.output(line)
|
||||
}
|
||||
} else {
|
||||
p.output(line)
|
||||
}
|
||||
@ -125,6 +132,13 @@ func (p *parser) benchmark(name, iterations, nsPerOp, mbPerSec, bytesPerOp, allo
|
||||
})
|
||||
}
|
||||
|
||||
func (p *parser) buildOutput(packageName string) {
|
||||
p.add(gtr.Event{
|
||||
Type: "build_output",
|
||||
Name: packageName,
|
||||
})
|
||||
}
|
||||
|
||||
func (p *parser) output(line string) {
|
||||
p.add(gtr.Event{Type: "output", Data: line})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user