90 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package printers
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"encoding/xml"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"sort"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/golangci/golangci-lint/pkg/result"
 | 
						|
)
 | 
						|
 | 
						|
type testSuitesXML struct {
 | 
						|
	XMLName    xml.Name `xml:"testsuites"`
 | 
						|
	TestSuites []testSuiteXML
 | 
						|
}
 | 
						|
 | 
						|
type testSuiteXML struct {
 | 
						|
	XMLName   xml.Name      `xml:"testsuite"`
 | 
						|
	Suite     string        `xml:"name,attr"`
 | 
						|
	Tests     int           `xml:"tests,attr"`
 | 
						|
	Errors    int           `xml:"errors,attr"`
 | 
						|
	Failures  int           `xml:"failures,attr"`
 | 
						|
	TestCases []testCaseXML `xml:"testcase"`
 | 
						|
}
 | 
						|
 | 
						|
type testCaseXML struct {
 | 
						|
	Name      string     `xml:"name,attr"`
 | 
						|
	ClassName string     `xml:"classname,attr"`
 | 
						|
	Failure   failureXML `xml:"failure"`
 | 
						|
}
 | 
						|
 | 
						|
type failureXML struct {
 | 
						|
	Message string `xml:"message,attr"`
 | 
						|
	Type    string `xml:"type,attr"`
 | 
						|
	Content string `xml:",cdata"`
 | 
						|
}
 | 
						|
 | 
						|
type JunitXML struct {
 | 
						|
	w io.Writer
 | 
						|
}
 | 
						|
 | 
						|
func NewJunitXML(w io.Writer) *JunitXML {
 | 
						|
	return &JunitXML{w: w}
 | 
						|
}
 | 
						|
 | 
						|
func (p JunitXML) Print(ctx context.Context, issues []result.Issue) error {
 | 
						|
	suites := make(map[string]testSuiteXML) // use a map to group by file
 | 
						|
 | 
						|
	for ind := range issues {
 | 
						|
		i := &issues[ind]
 | 
						|
		suiteName := i.FilePath()
 | 
						|
		testSuite := suites[suiteName]
 | 
						|
		testSuite.Suite = i.FilePath()
 | 
						|
		testSuite.Tests++
 | 
						|
		testSuite.Failures++
 | 
						|
 | 
						|
		tc := testCaseXML{
 | 
						|
			Name:      i.FromLinter,
 | 
						|
			ClassName: i.Pos.String(),
 | 
						|
			Failure: failureXML{
 | 
						|
				Type:    i.Severity,
 | 
						|
				Message: i.Pos.String() + ": " + i.Text,
 | 
						|
				Content: fmt.Sprintf("%s: %s\nCategory: %s\nFile: %s\nLine: %d\nDetails: %s",
 | 
						|
					i.Severity, i.Text, i.FromLinter, i.Pos.Filename, i.Pos.Line, strings.Join(i.SourceLines, "\n")),
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		testSuite.TestCases = append(testSuite.TestCases, tc)
 | 
						|
		suites[suiteName] = testSuite
 | 
						|
	}
 | 
						|
 | 
						|
	var res testSuitesXML
 | 
						|
	for _, val := range suites {
 | 
						|
		res.TestSuites = append(res.TestSuites, val)
 | 
						|
	}
 | 
						|
 | 
						|
	sort.Slice(res.TestSuites, func(i, j int) bool {
 | 
						|
		return res.TestSuites[i].Suite < res.TestSuites[j].Suite
 | 
						|
	})
 | 
						|
 | 
						|
	enc := xml.NewEncoder(p.w)
 | 
						|
	enc.Indent("", "  ")
 | 
						|
	if err := enc.Encode(res); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 |