@@ -20,6 +20,7 @@ import (
2020 "bufio"
2121 "bytes"
2222 "context"
23+ "encoding/xml"
2324 "fmt"
2425 "log"
2526 "math/rand"
@@ -102,6 +103,39 @@ var (
102103 runCoverage = pflag .Bool ("coverage" , false , "Set true to calculate test coverage" )
103104)
104105
106+ type TestSuites struct {
107+ XMLName xml.Name `xml:"testsuites"`
108+ Tests int `xml:"tests,attr"`
109+ Failures int `xml:"failures,attr"`
110+ Errors int `xml:"errors,attr"`
111+ Time float64 `xml:"time,attr"`
112+ TestSuites []TestSuite `xml:"testsuite"`
113+ }
114+
115+ type TestSuite struct {
116+ XMLName xml.Name `xml:"testsuite"`
117+ Name string `xml:"name,attr"`
118+ Tests int `xml:"tests,attr"`
119+ Failures int `xml:"failures,attr"`
120+ Time float64 `xml:"time,attr"`
121+ Timestamp string `xml:"timestamp,attr,omitempty"`
122+ TestCases []TestCase `xml:"testcase"`
123+ Properties []Property `xml:"properties>property,omitempty"`
124+ }
125+
126+ type TestCase struct {
127+ XMLName xml.Name `xml:"testcase"`
128+ ClassName string `xml:"classname,attr"`
129+ Name string `xml:"name,attr"`
130+ Time float64 `xml:"time,attr"`
131+ }
132+
133+ type Property struct {
134+ XMLName xml.Name `xml:"property"`
135+ Name string `xml:"name,attr"`
136+ Value string `xml:"value,attr"`
137+ }
138+
105139func commandWithContext (ctx context.Context , args ... string ) * exec.Cmd {
106140 cmd := exec .CommandContext (ctx , args [0 ], args [1 :]... ) //nolint:gosec
107141 cmd .Stdout = os .Stdout
@@ -265,8 +299,53 @@ func stopCluster(composeFile, prefix string, wg *sync.WaitGroup, err error) {
265299 }()
266300}
267301
268- func runTestsFor (ctx context.Context , pkg , prefix string ) error {
269- var args = []string {"go" , "test" , "-failfast" , "-v" , "-tags=integration" }
302+ func combineJUnitXML (outputFile string , files []string ) error {
303+ if len (files ) == 0 {
304+ return fmt .Errorf ("no files to merge" )
305+ }
306+
307+ combined := & TestSuites {}
308+ for _ , file := range files {
309+ data , err := os .ReadFile (file )
310+ if err != nil {
311+ return fmt .Errorf ("failed to read file %s: %w" , file , err )
312+ }
313+
314+ var suites TestSuites
315+ if err := xml .Unmarshal (data , & suites ); err != nil {
316+ return fmt .Errorf ("failed to parse XML from %s: %w" , file , err )
317+ }
318+
319+ // Aggregate data into the combined structure
320+ combined .Tests += suites .Tests
321+ combined .Failures += suites .Failures
322+ combined .Errors += suites .Errors
323+ combined .Time += suites .Time
324+ combined .TestSuites = append (combined .TestSuites , suites .TestSuites ... )
325+ }
326+
327+ output , err := xml .MarshalIndent (combined , "" , " " )
328+ if err != nil {
329+ return fmt .Errorf ("failed to marshal combined XML: %w" , err )
330+ }
331+
332+ output = append ([]byte (xml .Header ), output ... )
333+
334+ if err := os .WriteFile (outputFile , output , 0644 ); err != nil {
335+ return fmt .Errorf ("failed to write output file: %w" , err )
336+ }
337+
338+ fmt .Printf ("Combined XML written to %s\n " , outputFile )
339+ return nil
340+ }
341+
342+ func sanitizeFilename (pkg string ) string {
343+ return strings .ReplaceAll (pkg , "/" , "_" )
344+ }
345+
346+ func runTestsFor (ctx context.Context , pkg , prefix string , xmlFile string ) error {
347+ args := []string {"gotestsum" , "--junitfile" , xmlFile , "--format" , "standard-verbose" , "--max-fails" , "1" , "--" ,
348+ "-v" , "-failfast" , "-tags=integration" }
270349 if * race {
271350 args = append (args , "-timeout" , "180m" )
272351 // Todo: There are few race errors in tests itself. Enable this once that is fixed.
@@ -394,6 +473,27 @@ func runTests(taskCh chan task, closer *z.Closer) error {
394473 ctx := closer .Ctx ()
395474 ctx = context .WithValue (ctx , _threadIdKey {}, threadId )
396475
476+ tmpDir , err := os .MkdirTemp ("" , "dgraph-test-xml" )
477+ if err != nil {
478+ return fmt .Errorf ("failed to create temp directory: %v" , err )
479+ }
480+ defer func () {
481+ if err := os .RemoveAll (tmpDir ); err != nil {
482+ log .Printf ("Failed to remove temporary directory %s: %v" , tmpDir , err )
483+ }
484+ }()
485+
486+ var xmlFiles []string
487+
488+ defer func () {
489+ finalXMLFile := filepath .Join (* baseDir , "test-results.xml" )
490+ if err := combineJUnitXML (finalXMLFile , xmlFiles ); err != nil {
491+ log .Printf ("Error merging XML files: %v\n " , err )
492+ } else {
493+ fmt .Printf ("Merged test results into %s\n " , finalXMLFile )
494+ }
495+ }()
496+
397497 for task := range taskCh {
398498 if ctx .Err () != nil {
399499 err = ctx .Err ()
@@ -403,20 +503,22 @@ func runTests(taskCh chan task, closer *z.Closer) error {
403503 continue
404504 }
405505
506+ xmlFile := filepath .Join (tmpDir , sanitizeFilename (task .pkg .ID ))
507+ xmlFiles = append (xmlFiles , xmlFile ) // Add XML file path regardless of success or failure
406508 if task .isCommon {
407509 if * runCustom {
408510 // If we only need to run custom cluster tests, then skip this one.
409511 continue
410512 }
411513 start ()
412- if err = runTestsFor (ctx , task .pkg .ID , prefix ); err != nil {
514+ if err = runTestsFor (ctx , task .pkg .ID , prefix , xmlFile ); err != nil {
413515 // fmt.Printf("ERROR for package: %s. Err: %v\n", task.pkg.ID, err)
414516 return err
415517 }
416518 } else {
417519 // we are not using err variable here because we dont want to
418520 // print logs of default cluster in case of custom test fail.
419- if cerr := runCustomClusterTest (ctx , task .pkg .ID , wg ); cerr != nil {
521+ if cerr := runCustomClusterTest (ctx , task .pkg .ID , wg , xmlFile ); cerr != nil {
420522 return cerr
421523 }
422524 }
@@ -441,7 +543,7 @@ func getClusterPrefix() string {
441543}
442544
443545// for tests that require custom docker-compose file (located in test directory)
444- func runCustomClusterTest (ctx context.Context , pkg string , wg * sync.WaitGroup ) error {
546+ func runCustomClusterTest (ctx context.Context , pkg string , wg * sync.WaitGroup , xmlFile string ) error {
445547 fmt .Printf ("Bringing up cluster for package: %s\n " , pkg )
446548 var err error
447549 compose := composeFileFor (pkg )
@@ -455,7 +557,7 @@ func runCustomClusterTest(ctx context.Context, pkg string, wg *sync.WaitGroup) e
455557 defer stopCluster (compose , prefix , wg , err )
456558 }
457559
458- err = runTestsFor (ctx , pkg , prefix )
560+ err = runTestsFor (ctx , pkg , prefix , xmlFile )
459561 return err
460562}
461563
0 commit comments