first working version.

This commit is contained in:
Erik Brakkee 2024-11-20 21:13:17 +01:00
parent 7643f37b73
commit 8a2c4757b9
3 changed files with 335 additions and 2 deletions

View File

@ -1,7 +1,119 @@
package main package main
import "fmt" import (
"bufio"
"encoding/json"
"encoding/xml"
"fmt"
"os"
)
func main() { func main() {
fmt.Println("Hello")
/*
testsuites := Testsuites{
Time: 1.23,
TImestamp: time.Now(),
Suites: []*Testsuite{
{
Name: "hello",
Tests: 0,
Failures: 0,
Errors: 0,
Disabled: 0,
Package: "",
Skipped: 0,
Time: "",
Timestamp: time.Now(),
Testsuites: []*Testsuite{
{
Name: "abc",
Tests: 0,
Failures: 0,
Errors: 0,
Disabled: 0,
Package: "",
Skipped: 0,
Time: "",
Timestamp: time.Time{},
Testsuites: nil,
Testcases: []*Testcase{
{
Name: "test",
Classname: "",
Time: "",
Skipped: nil,
Error: &Result{
Message: "error",
},
Failure: nil,
SystemOut: "",
},
},
SystemOut: "ddd",
},
},
Testcases: nil,
SystemOut: "hello",
},
},
}
*/
testsuites := Testsuites{}
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "Usage: go2junit <gotest.json>\n")
os.Exit(1)
}
filename := os.Args[1]
file, _ := os.Open(filename)
defer file.Close()
scanner := bufio.NewScanner(file)
lineno := 0
testsuites = Testsuites{}
for scanner.Scan() {
lineno++
var item TestEvent
line := scanner.Bytes()
if err := json.Unmarshal(line, &item); err != nil {
fmt.Fprintf(os.Stderr, "%d: %s: %v", lineno, line, err)
continue
}
//.fmt.Printf("Parsed %d:\n%v\n\n", lineno, item)
switch item.Action {
case "start":
testsuites.Suite(item.Time, item.Package)
case "run":
testsuites.Test(item.Time, item.Package, item.Test)
case "output":
testsuites.Output(item.Time, item.Package, item.Test, item.Output)
fmt.Fprintf(os.Stderr, "%s", item.Output)
case "pause":
testsuites.Output(item.Time, item.Package, item.Test, "PAUSED")
case "cont":
testsuites.Output(item.Time, item.Package, item.Test, "CONTINUED")
case "pass":
testsuites.Pass(item.Time, item.Package, item.Test, item.Elapsed)
case "bench":
testsuites.Bench(item.Time, item.Package, item.Test, item.Output, item.Elapsed)
case "fail":
testsuites.Fail(item.Time, item.Package, item.Test, item.Elapsed)
case "skip":
testsuites.Skip(item.Time, item.Package, item.Test)
}
}
testsuites.Complete()
xml, err := xml.MarshalIndent(testsuites, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s", xml)
} }

12
cmd/go2junit/input.go Normal file
View File

@ -0,0 +1,12 @@
package main
import "time"
type TestEvent struct {
Time time.Time
Action string
Package string
Test string
Elapsed float64
Output string
}

209
cmd/go2junit/output.go Normal file
View File

@ -0,0 +1,209 @@
package main
import (
"encoding/xml"
"log"
"strings"
"time"
)
type Testsuites struct {
XMLName xml.Name `xml:"testsuites"`
Tests int `xml:"tests,attr"`
Failures int `xml:"failures,attr"`
Errors int `xml:"errors,attr"`
Disabled int `xml:"disabled,attr,omitempty"`
Skipped int `xml:"skipped,attr,omitempty"`
Time float64 `xml:"time,attr"`
Suites []*Testsuite `xml:"testsuite,omitempty"`
}
type Testsuite struct {
// required attributes
Name string `xml:"name,attr"`
Tests int `xml:"tests,attr"`
Failures int `xml:"failures,attr"`
Errors int `xml:"errors,attr"`
// optional attributes
Disabled int `xml:"disabled,attr,omitempty"`
Package string `xml:"package,attr,omitempty"`
Skipped int `xml:"skipped,attr,omitempty"`
Time string `xml:"time,attr"`
Timestamp time.Time `xml:"timestamp,attr,omitempty"`
Testsuites []*Testsuite `xml:"testsuite,omitempty"`
Testcases []*Testcase `xml:"testcase,omitempty"`
SystemOut string `xml:"system-out,omitempty"`
}
type Result struct {
Message string `xml:"message,attr"`
}
type Testcase struct {
// required attributes
Name string `xml:"name,attr"`
Classname string `xml:"classname,attr"`
// optional attributes
Time float64 `xml:"time,attr,omitempty"`
Skipped *Result `xml:"skipped,omitempty"`
Error *Result `xml:"error,omitempty"`
Failure *Result `xml:"failure,omitempty"`
SystemOut string `xml:"system-out,omitempty"`
}
func (testsuites *Testsuites) getSuite(t time.Time, pkg string) *Testsuite {
for _, suite := range testsuites.Suites {
if suite.Name == pkg {
return suite
}
}
suite := Testsuite{
Name: pkg,
Skipped: 0,
Timestamp: t,
}
log.Printf("Adding suite %s", pkg)
testsuites.Suites = append(testsuites.Suites, &suite)
return &suite
}
func (suite *Testsuite) getSuite(t time.Time, name string) *Testsuite {
for _, s := range suite.Testsuites {
if s.Name == name {
return s
}
}
s := Testsuite{
Name: name,
Timestamp: t,
}
suite.Testsuites = append(suite.Testsuites, &s)
return &s
}
func (suite *Testsuite) getTest(t time.Time, testname string) *Testcase {
path := strings.Split(testname, "/")
for i := 0; i < len(path)-1; i++ {
suite = suite.getSuite(t, path[i])
}
for _, test := range suite.Testcases {
if test.Name == path[len(path)-1] {
return test
}
}
if path[len(path)-1] == "" {
panic("Empty testcase")
}
test := Testcase{
Name: path[len(path)-1],
}
suite.Testcases = append(suite.Testcases, &test)
return &test
}
func (testsuites *Testsuites) getTest(t time.Time, pkg string, testname string) *Testcase {
suite := testsuites.getSuite(t, pkg)
test := suite.getTest(t, testname)
return test
}
func (testsuites *Testsuites) Suite(t time.Time, pkg string) {
testsuites.getSuite(t, pkg)
}
func (testsuites *Testsuites) Test(t time.Time, pkg string, test string) {
testsuites.getTest(t, pkg, test)
}
func (testsuites *Testsuites) Output(t time.Time, pkg string, test string, output string) {
if test == "" {
ts := testsuites.getSuite(t, pkg)
ts.SystemOut = ts.SystemOut + output
return
}
tc := testsuites.getTest(t, pkg, test)
tc.SystemOut = tc.SystemOut + output
}
func (testsuites *Testsuites) Pass(t time.Time, pkg string, test string, elapsed float64) {
if test == "" {
return
}
testsuites.getTest(t, pkg, test)
}
func (testsuites *Testsuites) Bench(t time.Time, pkg string, test string, output string, elapsed float64) {
tc := testsuites.getTest(t, pkg, test)
tc.SystemOut = tc.SystemOut + output + "\n"
}
func (testsuites *Testsuites) Fail(t time.Time, pkg string, test string, elapsed float64) {
if test == "" {
return
}
tc := testsuites.getTest(t, pkg, test)
tc.Time = elapsed
tc.Failure = &Result{
Message: "failed",
}
}
func (testsuites *Testsuites) Skip(t time.Time, pkg string, test string) {
if test == "" {
return
}
tc := testsuites.getTest(t, pkg, test)
tc.Failure = &Result{
Message: "skipped",
}
}
func (suite *Testsuite) Complete() {
suite.Tests = 0
suite.Failures = 0
suite.Errors = 0
suite.Disabled = 0
suite.Skipped = 0
for _, ts := range suite.Testsuites {
ts.Complete()
suite.Tests += ts.Tests
suite.Failures += ts.Failures
suite.Errors += ts.Errors
suite.Disabled += ts.Disabled
suite.Skipped += ts.Skipped
}
for _, tc := range suite.Testcases {
suite.Tests += 1
if tc.Failure != nil {
switch tc.Failure.Message {
case "skipped":
suite.Skipped++
default:
suite.Failures++
}
}
}
}
func (testsuites *Testsuites) Complete() {
testsuites.Tests = 0
testsuites.Failures = 0
testsuites.Errors = 0
testsuites.Disabled = 0
testsuites.Skipped = 0
for _, ts := range testsuites.Suites {
ts.Complete()
testsuites.Tests += ts.Tests
testsuites.Failures += ts.Failures
testsuites.Errors += ts.Errors
testsuites.Disabled += ts.Disabled
testsuites.Skipped += ts.Skipped
}
}