github.com/nozzle/golangci-lint@v1.49.0-nz3/pkg/printers/junitxml.go (about) 1 package printers 2 3 import ( 4 "context" 5 "encoding/xml" 6 "fmt" 7 "io" 8 "sort" 9 "strings" 10 11 "github.com/golangci/golangci-lint/pkg/result" 12 ) 13 14 type testSuitesXML struct { 15 XMLName xml.Name `xml:"testsuites"` 16 TestSuites []testSuiteXML 17 } 18 19 type testSuiteXML struct { 20 XMLName xml.Name `xml:"testsuite"` 21 Suite string `xml:"name,attr"` 22 Tests int `xml:"tests,attr"` 23 Errors int `xml:"errors,attr"` 24 Failures int `xml:"failures,attr"` 25 TestCases []testCaseXML `xml:"testcase"` 26 } 27 28 type testCaseXML struct { 29 Name string `xml:"name,attr"` 30 ClassName string `xml:"classname,attr"` 31 Failure failureXML `xml:"failure"` 32 } 33 34 type failureXML struct { 35 Message string `xml:"message,attr"` 36 Type string `xml:"type,attr"` 37 Content string `xml:",cdata"` 38 } 39 40 type JunitXML struct { 41 w io.Writer 42 } 43 44 func NewJunitXML(w io.Writer) *JunitXML { 45 return &JunitXML{w: w} 46 } 47 48 func (p JunitXML) Print(ctx context.Context, issues []result.Issue) error { 49 suites := make(map[string]testSuiteXML) // use a map to group by file 50 51 for ind := range issues { 52 i := &issues[ind] 53 suiteName := i.FilePath() 54 testSuite := suites[suiteName] 55 testSuite.Suite = i.FilePath() 56 testSuite.Tests++ 57 testSuite.Failures++ 58 59 tc := testCaseXML{ 60 Name: i.FromLinter, 61 ClassName: i.Pos.String(), 62 Failure: failureXML{ 63 Type: i.Severity, 64 Message: i.Pos.String() + ": " + i.Text, 65 Content: fmt.Sprintf("%s: %s\nCategory: %s\nFile: %s\nLine: %d\nDetails: %s", 66 i.Severity, i.Text, i.FromLinter, i.Pos.Filename, i.Pos.Line, strings.Join(i.SourceLines, "\n")), 67 }, 68 } 69 70 testSuite.TestCases = append(testSuite.TestCases, tc) 71 suites[suiteName] = testSuite 72 } 73 74 var res testSuitesXML 75 for _, val := range suites { 76 res.TestSuites = append(res.TestSuites, val) 77 } 78 79 sort.Slice(res.TestSuites, func(i, j int) bool { 80 return res.TestSuites[i].Suite < res.TestSuites[j].Suite 81 }) 82 83 enc := xml.NewEncoder(p.w) 84 enc.Indent("", " ") 85 if err := enc.Encode(res); err != nil { 86 return err 87 } 88 return nil 89 }