mirror of
https://github.com/jstemmer/go-junit-report.git
synced 2025-04-05 05:00:15 -05:00
gtr: Extract report builder to separate file
This commit is contained in:
parent
c6349bc2f5
commit
7bc0f1a86b
108
pkg/gtr/builder.go
Normal file
108
pkg/gtr/builder.go
Normal file
@ -0,0 +1,108 @@
|
||||
package gtr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ReportBuilder builds Reports.
|
||||
type ReportBuilder struct {
|
||||
packages []Package
|
||||
tests map[int]Test
|
||||
|
||||
// state
|
||||
nextId int // next free id
|
||||
lastId int // last test id // TODO: stack?
|
||||
output []string
|
||||
}
|
||||
|
||||
func NewReportBuilder() *ReportBuilder {
|
||||
return &ReportBuilder{
|
||||
tests: make(map[int]Test),
|
||||
nextId: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) flush() {
|
||||
if len(b.tests) > 0 {
|
||||
b.CreatePackage("unknown", 0)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) Build() Report {
|
||||
b.flush()
|
||||
return Report{Packages: b.packages}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) CreateTest(name string) {
|
||||
id := b.nextId
|
||||
b.lastId = id
|
||||
|
||||
b.nextId += 1
|
||||
b.tests[id] = Test{Name: name}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) EndTest(name, result string, duration time.Duration) {
|
||||
id := b.findTest(name)
|
||||
b.lastId = id
|
||||
|
||||
t := b.tests[id]
|
||||
t.Result = parseResult(result)
|
||||
t.Duration = duration
|
||||
b.tests[id] = t
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) CreatePackage(name string, duration time.Duration) {
|
||||
var tests []Test
|
||||
for id := 1; id < b.nextId; id++ {
|
||||
tests = append(tests, b.tests[id])
|
||||
}
|
||||
b.packages = append(b.packages, Package{
|
||||
Name: name,
|
||||
Duration: duration,
|
||||
Tests: tests,
|
||||
Output: b.output,
|
||||
})
|
||||
|
||||
b.tests = make(map[int]Test)
|
||||
b.output = nil
|
||||
b.nextId = 1
|
||||
b.lastId = 0
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) AppendOutput(line string) {
|
||||
if b.lastId <= 0 {
|
||||
b.output = append(b.output, line)
|
||||
return
|
||||
}
|
||||
t := b.tests[b.lastId]
|
||||
t.Output = append(t.Output, line)
|
||||
b.tests[b.lastId] = t
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) findTest(name string) int {
|
||||
// check if this test was lastId
|
||||
if t, ok := b.tests[b.lastId]; ok && t.Name == name {
|
||||
return b.lastId
|
||||
}
|
||||
for id := len(b.tests); id >= 0; id-- {
|
||||
if b.tests[id].Name == name {
|
||||
return id
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func parseResult(r string) Result {
|
||||
switch r {
|
||||
case "PASS":
|
||||
return PASS
|
||||
case "FAIL":
|
||||
return FAIL
|
||||
case "SKIP":
|
||||
return SKIP
|
||||
default:
|
||||
fmt.Printf("unknown result: %q\n", r)
|
||||
return UNKNOWN
|
||||
}
|
||||
}
|
3
pkg/gtr/event.go
Normal file
3
pkg/gtr/event.go
Normal file
@ -0,0 +1,3 @@
|
||||
package gtr
|
||||
|
||||
// TODO: define gtop.Event here for easy re-use across different parser
|
124
pkg/gtr/gtr.go
124
pkg/gtr/gtr.go
@ -1,11 +1,14 @@
|
||||
// Package gtr generates Go Test Reports from a collection of Events.
|
||||
// Package gtr defines a standard test report format and provides convenience
|
||||
// methods to create and convert reports.
|
||||
package gtr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jstemmer/go-junit-report/v2/pkg/parser/gotest"
|
||||
"github.com/jstemmer/go-junit-report/v2/pkg/junit"
|
||||
)
|
||||
|
||||
type Result int
|
||||
@ -37,6 +40,17 @@ type Report struct {
|
||||
Packages []Package
|
||||
}
|
||||
|
||||
func (r *Report) HasFailures() bool {
|
||||
for _, pkg := range r.Packages {
|
||||
for _, t := range pkg.Tests {
|
||||
if t.Result == FAIL {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
Name string
|
||||
Duration time.Duration
|
||||
@ -53,15 +67,15 @@ type Test struct {
|
||||
Output []string
|
||||
}
|
||||
|
||||
// FromEvents creates a Report from the given list of test events.
|
||||
// FromEvents creates a Report from the given list of events.
|
||||
func FromEvents(events []gotest.Event) Report {
|
||||
report := NewReportBuilder()
|
||||
for _, ev := range events {
|
||||
switch ev.Type {
|
||||
case "run_test":
|
||||
report.CreateTest(ev.Id, ev.Name)
|
||||
report.CreateTest(ev.Name)
|
||||
case "end_test":
|
||||
report.EndTest(ev.Id, ev.Result, ev.Duration)
|
||||
report.EndTest(ev.Name, ev.Result, ev.Duration)
|
||||
case "status": // ignore for now
|
||||
case "summary":
|
||||
report.CreatePackage(ev.Name, ev.Duration)
|
||||
@ -74,87 +88,35 @@ func FromEvents(events []gotest.Event) Report {
|
||||
return report.Build()
|
||||
}
|
||||
|
||||
// ReportBuilder builds Reports.
|
||||
type ReportBuilder struct {
|
||||
packages []Package
|
||||
ids []int
|
||||
tests map[int]Test
|
||||
|
||||
// state
|
||||
output []string
|
||||
last int // last test id // TODO: stack?
|
||||
}
|
||||
|
||||
func NewReportBuilder() *ReportBuilder {
|
||||
return &ReportBuilder{
|
||||
tests: make(map[int]Test),
|
||||
// JUnit converts the given report to a collection of JUnit Testsuites.
|
||||
func JUnit(report Report) junit.Testsuites {
|
||||
var suites junit.Testsuites
|
||||
for _, pkg := range report.Packages {
|
||||
suite := junit.Testsuite{
|
||||
Name: pkg.Name,
|
||||
Tests: len(pkg.Tests),
|
||||
Time: junit.FormatDuration(pkg.Duration),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) flush() {
|
||||
if len(b.tests) > 0 {
|
||||
b.CreatePackage("unknown", 0)
|
||||
for _, test := range pkg.Tests {
|
||||
tc := junit.Testcase{
|
||||
Classname: pkg.Name,
|
||||
Name: test.Name,
|
||||
Time: junit.FormatDuration(test.Duration),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) Build() Report {
|
||||
b.flush()
|
||||
return Report{Packages: b.packages}
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) CreateTest(id int, name string) {
|
||||
b.ids = append(b.ids, id)
|
||||
b.tests[id] = Test{Name: name}
|
||||
|
||||
b.last = id
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) EndTest(id int, result string, duration time.Duration) {
|
||||
t := b.tests[id]
|
||||
t.Result = parseResult(result)
|
||||
t.Duration = duration
|
||||
b.tests[id] = t
|
||||
|
||||
b.last = id
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) CreatePackage(name string, duration time.Duration) {
|
||||
var tests []Test
|
||||
for _, id := range b.ids {
|
||||
tests = append(tests, b.tests[id])
|
||||
if test.Result == FAIL {
|
||||
tc.Failure = &junit.Result{
|
||||
Message: "Failed",
|
||||
Data: strings.Join(test.Output, "\n"),
|
||||
}
|
||||
b.packages = append(b.packages, Package{
|
||||
Name: name,
|
||||
Duration: duration,
|
||||
Tests: tests,
|
||||
Output: b.output,
|
||||
})
|
||||
|
||||
b.ids = nil
|
||||
b.tests = make(map[int]Test)
|
||||
b.output = nil
|
||||
}
|
||||
|
||||
func (b *ReportBuilder) AppendOutput(line string) {
|
||||
if b.last <= 0 {
|
||||
b.output = append(b.output, line)
|
||||
return
|
||||
} else if test.Result == SKIP {
|
||||
tc.Skipped = &junit.Result{
|
||||
Data: strings.Join(test.Output, "\n"),
|
||||
}
|
||||
t := b.tests[b.last]
|
||||
t.Output = append(t.Output, line)
|
||||
b.tests[b.last] = t
|
||||
}
|
||||
|
||||
func parseResult(r string) Result {
|
||||
switch r {
|
||||
case "PASS":
|
||||
return PASS
|
||||
case "FAIL":
|
||||
return FAIL
|
||||
case "SKIP":
|
||||
return SKIP
|
||||
default:
|
||||
fmt.Printf("unknown result: %q\n", r)
|
||||
return UNKNOWN
|
||||
}
|
||||
suite.AddTestcase(tc)
|
||||
}
|
||||
suites.AddSuite(suite)
|
||||
}
|
||||
return suites
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user