diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index ccf4e440..b227a3ec 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -70,6 +70,7 @@ output: # - `checkstyle` # - `code-climate` # - `junit-xml` + # - `junit-xml-extended` # - `github-actions` # - `teamcity` # - `sarif` diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 0272f445..d90e78ba 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -521,6 +521,7 @@ "checkstyle", "code-climate", "junit-xml", + "junit-xml-extended", "github-actions", "teamcity", "sarif" diff --git a/pkg/config/output.go b/pkg/config/output.go index 592e293e..6a26d577 100644 --- a/pkg/config/output.go +++ b/pkg/config/output.go @@ -17,6 +17,7 @@ const ( OutFormatCodeClimate = "code-climate" OutFormatHTML = "html" OutFormatJunitXML = "junit-xml" + OutFormatJunitXMLExtended = "junit-xml-extended" OutFormatGithubActions = "github-actions" // Deprecated OutFormatTeamCity = "teamcity" OutFormatSarif = "sarif" @@ -32,6 +33,7 @@ var AllOutputFormats = []string{ OutFormatCodeClimate, OutFormatHTML, OutFormatJunitXML, + OutFormatJunitXMLExtended, OutFormatGithubActions, OutFormatTeamCity, OutFormatSarif, diff --git a/pkg/printers/junitxml.go b/pkg/printers/junitxml.go index 3e3f82f5..7d0a703b 100644 --- a/pkg/printers/junitxml.go +++ b/pkg/printers/junitxml.go @@ -30,6 +30,8 @@ type testCaseXML struct { Name string `xml:"name,attr"` ClassName string `xml:"classname,attr"` Failure failureXML `xml:"failure"` + File string `xml:"file,attr,omitempty"` + Line int `xml:"line,attr,omitempty"` } type failureXML struct { @@ -39,11 +41,15 @@ type failureXML struct { } type JunitXML struct { - w io.Writer + extended bool + w io.Writer } -func NewJunitXML(w io.Writer) *JunitXML { - return &JunitXML{w: w} +func NewJunitXML(extended bool, w io.Writer) *JunitXML { + return &JunitXML{ + extended: extended, + w: w, + } } func (p JunitXML) Print(issues []result.Issue) error { @@ -68,6 +74,11 @@ func (p JunitXML) Print(issues []result.Issue) error { }, } + if p.extended { + tc.File = i.Pos.Filename + tc.Line = i.Pos.Line + } + testSuite.TestCases = append(testSuite.TestCases, tc) suites[suiteName] = testSuite } diff --git a/pkg/printers/junitxml_test.go b/pkg/printers/junitxml_test.go index d5b4bc1f..e4dfde19 100644 --- a/pkg/printers/junitxml_test.go +++ b/pkg/printers/junitxml_test.go @@ -42,13 +42,14 @@ func TestJunitXML_Print(t *testing.T) { }, } - buf := new(bytes.Buffer) - printer := NewJunitXML(buf) - - err := printer.Print(issues) - require.NoError(t, err) - - expected := `<testsuites> + testCases := []struct { + desc string + extended bool + expected string + }{ + { + desc: "basic", + expected: `<testsuites> <testsuite name="path/to/filea.go" tests="1" errors="0" failures="1"> <testcase name="linter-a" classname="path/to/filea.go:10:4"> <failure message="path/to/filea.go:10:4: some issue" type="warning"><![CDATA[warning: some issue @@ -69,7 +70,47 @@ Details: func foo() { }]]></failure> </testcase> </testsuite> -</testsuites>` +</testsuites>`, + }, + { + desc: "extended/complete", + extended: true, + expected: `<testsuites> + <testsuite name="path/to/filea.go" tests="1" errors="0" failures="1"> + <testcase name="linter-a" classname="path/to/filea.go:10:4" file="path/to/filea.go" line="10"> + <failure message="path/to/filea.go:10:4: some issue" type="warning"><![CDATA[warning: some issue +Category: linter-a +File: path/to/filea.go +Line: 10 +Details: ]]></failure> + </testcase> + </testsuite> + <testsuite name="path/to/fileb.go" tests="1" errors="0" failures="1"> + <testcase name="linter-b" classname="path/to/fileb.go:300:9" file="path/to/fileb.go" line="300"> + <failure message="path/to/fileb.go:300:9: another issue" type="error"><![CDATA[error: another issue +Category: linter-b +File: path/to/fileb.go +Line: 300 +Details: func foo() { + fmt.Println("bar") +}]]></failure> + </testcase> + </testsuite> +</testsuites>`, + }, + } - assert.Equal(t, expected, buf.String()) + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + buf := new(bytes.Buffer) + printer := NewJunitXML(test.extended, buf) + + err := printer.Print(issues) + require.NoError(t, err) + + assert.Equal(t, test.expected, buf.String()) + }) + } } diff --git a/pkg/printers/printer.go b/pkg/printers/printer.go index 53db0122..20be02e0 100644 --- a/pkg/printers/printer.go +++ b/pkg/printers/printer.go @@ -115,7 +115,7 @@ func (c *Printer) createPrinter(format string, w io.Writer) (issuePrinter, error switch format { case config.OutFormatJSON: p = NewJSON(c.reportData, w) - case config.OutFormatColoredLineNumber, config.OutFormatLineNumber: + case config.OutFormatLineNumber, config.OutFormatColoredLineNumber: p = NewText(c.cfg.PrintIssuedLine, format == config.OutFormatColoredLineNumber, c.cfg.PrintLinterName, c.log.Child(logutils.DebugKeyTextPrinter), w) @@ -129,8 +129,8 @@ func (c *Printer) createPrinter(format string, w io.Writer) (issuePrinter, error p = NewCodeClimate(w) case config.OutFormatHTML: p = NewHTML(w) - case config.OutFormatJunitXML: - p = NewJunitXML(w) + case config.OutFormatJunitXML, config.OutFormatJunitXMLExtended: + p = NewJunitXML(format == config.OutFormatJunitXMLExtended, w) case config.OutFormatGithubActions: p = NewGitHubAction(w) case config.OutFormatTeamCity: