From e20795e7b9cc7e182a29d37f97220601920769ab Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Fri, 22 Nov 2024 20:59:23 +0100 Subject: [PATCH] no more duplication of test suites. Parsing the test tree and deciding in the marsheller whether it is a testcase (leaf) or a suite (non-leaf) --- cmd/go2junit/go2junit.go | 37 ++++++++++++- cmd/go2junit/output.go | 117 +++++++++++++++++++-------------------- 2 files changed, 92 insertions(+), 62 deletions(-) diff --git a/cmd/go2junit/go2junit.go b/cmd/go2junit/go2junit.go index 2f55e40..c84af0f 100644 --- a/cmd/go2junit/go2junit.go +++ b/cmd/go2junit/go2junit.go @@ -9,8 +9,43 @@ import ( "path/filepath" ) -func main() { +func (t *Test) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + if len(t.Tests) == 0 { + start.Name = xml.Name{Local: "testcase"} + classname := "" + if t.Parent != nil { + classname = t.Parent.Name + } + var skipped *Result + if t.Skipped > 0 { + skipped = &Result{ + Message: "skipped", + } + } + var failed *Result + if t.Failures > 0 { + failed = &Result{ + Message: "failed", + } + } + tc := Testcase{ + Name: t.Name, + // parent class name + Classname: classname, + Time: t.Time, + Skipped: skipped, + Error: nil, + Failure: failed, + SystemOut: t.SystemOut, + } + return e.EncodeElement(tc, start) + } + type Alias Test + start.Name = xml.Name{Local: "testsuite"} + return e.EncodeElement(Alias(*t), start) +} +func main() { /* testsuites := Testsuites{ Time: 1.23, diff --git a/cmd/go2junit/output.go b/cmd/go2junit/output.go index ce0c17e..dde314f 100644 --- a/cmd/go2junit/output.go +++ b/cmd/go2junit/output.go @@ -18,28 +18,29 @@ type Testsuites struct { Time float64 `xml:"time,attr"` - Suites []*Testsuite `xml:"testsuite,omitempty"` + Suites []*Test `xml:"testsuite,omitempty"` } -type Testsuite struct { +type Test struct { XMLName xml.Name `xml:"testsuite"` // required attributes - Name string `xml:"name,attr"` - Tests int `xml:"tests,attr"` - Failures int `xml:"failures,attr"` - Errors int `xml:"errors,attr"` + Name string `xml:"name,attr"` + TestCount 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"` + Time float64 `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"` + Tests []*Test `xml:"testsuite,omitempty"` + SystemOut string `xml:"system-out,omitempty"` + + Parent *Test `xml:"-"` } type Result struct { @@ -60,13 +61,17 @@ type Testcase struct { SystemOut string `xml:"system-out,omitempty"` } -func (testsuites *Testsuites) getSuite(t time.Time, pkg string) *Testsuite { +// Looks for a test in root +func (testsuites *Testsuites) getRootSuite(t time.Time, pkg string, create bool) *Test { for _, suite := range testsuites.Suites { if suite.Name == pkg { return suite } } - suite := Testsuite{ + if !create { + return nil + } + suite := Test{ Name: pkg, Skipped: 0, Timestamp: t, @@ -76,62 +81,53 @@ func (testsuites *Testsuites) getSuite(t time.Time, pkg string) *Testsuite { return &suite } -func (suite *Testsuite) getSuite(t time.Time, name string) *Testsuite { - for _, s := range suite.Testsuites { +func (suite *Test) getSuite(t time.Time, name string) *Test { + for _, s := range suite.Tests { if s.Name == suite.Name+"/"+name { return s } } - s := Testsuite{ + s := Test{ Name: suite.Name + "/" + name, Timestamp: t, } - suite.Testsuites = append(suite.Testsuites, &s) + suite.Tests = append(suite.Tests, &s) return &s } -func (suite *Testsuite) getTest(t time.Time, testname string) *Testcase { +func (suite *Test) getTest(t time.Time, testname string) *Test { suitename := suite.Name path := strings.Split(testname, "/") - for i := 0; i < len(path)-1; i++ { + for i := 0; i < len(path); i++ { suite = suite.getSuite(t, path[i]) suitename = suitename + "/" + path[i] } - testname = path[len(path)-1] - - for _, test := range suite.Testcases { - if test.Name == testname { - return test - } - } - if testname == "" { - panic("Empty testcase") - } - test := Testcase{ - Name: testname, - Classname: suitename, - } - suite.Testcases = append(suite.Testcases, &test) - return &test + return suite } -func (testsuites *Testsuites) getTest(t time.Time, pkg string, testname string) *Testcase { - suite := testsuites.getSuite(t, pkg) +func (testsuites *Testsuites) getTest(t time.Time, pkg string, testname string) *Test { + suite := testsuites.getRootSuite(t, pkg, true) test := suite.getTest(t, testname) return test } func (testsuites *Testsuites) Suite(t time.Time, pkg string) { - testsuites.getSuite(t, pkg) + testsuites.getRootSuite(t, pkg, true) } func (testsuites *Testsuites) Test(t time.Time, pkg string, test string) { + // This can be a test suite as well 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 := testsuites.getRootSuite(t, pkg, true) + ts.SystemOut = ts.SystemOut + output + return + } + ts := testsuites.getRootSuite(t, pkg+"/"+test, false) + if ts != nil { ts.SystemOut = ts.SystemOut + output return } @@ -143,7 +139,9 @@ func (testsuites *Testsuites) Pass(t time.Time, pkg string, test string, elapsed if test == "" { return } - testsuites.getTest(t, pkg, test) + if testsuites.getRootSuite(t, pkg+"/"+test, false) != nil { + return + } } func (testsuites *Testsuites) Bench(t time.Time, pkg string, test string, output string, elapsed float64) { @@ -155,47 +153,44 @@ func (testsuites *Testsuites) Fail(t time.Time, pkg string, test string, elapsed if test == "" { return } + if testsuites.getRootSuite(t, pkg+"/"+test, false) != nil { + return + } tc := testsuites.getTest(t, pkg, test) tc.Time = elapsed - tc.Failure = &Result{ - Message: "failed", - } + tc.Failures = 1 } 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", + if testsuites.getRootSuite(t, pkg+"/"+test, false) != nil { + return } + tc := testsuites.getTest(t, pkg, test) + tc.Skipped = 1 } -func (suite *Testsuite) Complete() { - suite.Tests = 0 +func (suite *Test) Complete() { + suite.TestCount = 0 suite.Failures = 0 suite.Errors = 0 suite.Disabled = 0 suite.Skipped = 0 - for _, ts := range suite.Testsuites { + + if len(suite.Tests) == 0 { + suite.TestCount = 1 + } + + for _, ts := range suite.Tests { ts.Complete() - suite.Tests += ts.Tests + suite.TestCount += ts.TestCount 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++ - } - } + ts.Parent = suite } } @@ -207,7 +202,7 @@ func (testsuites *Testsuites) Complete() { testsuites.Skipped = 0 for _, ts := range testsuites.Suites { ts.Complete() - testsuites.Tests += ts.Tests + testsuites.Tests += ts.TestCount testsuites.Failures += ts.Failures testsuites.Errors += ts.Errors testsuites.Disabled += ts.Disabled