Skip to content
This repository was archived by the owner on Nov 20, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmdline.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var args struct {
showVersion bool
bambooOut bool
xunitnetOut bool
sonarGTDOut bool
isGocheck bool
suitePrefix string
}
Expand All @@ -28,6 +29,7 @@ func init() {
flag.BoolVar(&args.bambooOut, "bamboo", false,
"xml compatible with Atlassian's Bamboo")
flag.BoolVar(&args.xunitnetOut, "xunitnet", false, "xml compatible with xunit.net")
flag.BoolVar(&args.sonarGTDOut, "sonar", false, "xml compatible with Sonar Generic Test Data")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add a check in main that it's no colliding with other formatting flags.

flag.BoolVar(&args.isGocheck, "gocheck", false, "parse gocheck output")
flag.BoolVar(&lib.Options.FailOnRace, "fail-on-race", false,
"mark test as failing if it exposes a data race")
Expand Down
48 changes: 48 additions & 0 deletions lib/file_path_parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package lib

import (
"go/build"
"io/ioutil"
"path/filepath"
"strings"
)

func fileFileForTest(suite *Suite, test *Test, pkg *build.Package, strip string) string {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I like the name fileFile prefix. Hard to understand what this does from the name, maybe a document?

var (
testFileContents = make(map[string]string)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually don't declare variables in advance, we use := instead

body []byte
testFilePath string
contents string
err error
ok bool
)
if strip == "" {
strip = pkg.SrcRoot + "/"
}
for _, testFile := range pkg.TestGoFiles {
testFilePath = filepath.Join(pkg.Dir, testFile)
if contents, ok = testFileContents[testFilePath]; !ok {
if body, err = ioutil.ReadFile(testFilePath); err != nil {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't ignore errors, unless there's a good reason

continue
}
contents = string(body)
testFileContents[testFilePath] = contents
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the test file contents in the XML example, why do we need it?

}
if strings.Contains(contents, test.Name) {
return strings.Replace(testFilePath, strip, "", 1)
}
}

return suite.Name
}

func tmplFuncFilePathForTest(suite *Suite, test *Test, strip string) string {
var (
pkg *build.Package
err error
)
if pkg, err = build.Import(suite.Name, build.Default.GOPATH, build.IgnoreVendor); err != nil {
return suite.Name
}
return fileFileForTest(suite, test, pkg, strip)
}
10 changes: 5 additions & 5 deletions lib/parsers.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func ParseGocheck(rd io.Reader, suitePrefix string) (Suites, error) {

for scanner.Scan() {
line := scanner.Text()

tokens := findStart(line)
if len(tokens) > 0 {
if tokens[2] == "SetUpTest" || tokens[2] == "TearDownTest" {
Expand Down Expand Up @@ -168,7 +168,7 @@ func ParseGotest(rd io.Reader, suitePrefix string) (Suites, error) {
var curSuite *Suite
var out []string
suiteStack := SuiteStack{}

// Handles a test that ended with a panic.
handlePanic := func() {
curTest.Status = Failed
Expand Down Expand Up @@ -279,19 +279,19 @@ func ParseGotest(rd io.Reader, suitePrefix string) (Suites, error) {
curTest.Status = Failed
}
curTest.Time = tokens[3]

if len(out) > 0 {
message := strings.Join(out, "\n")
prevTest, err := getPreviousFailTest(curSuite, curTest)
var test *Test
if err == nil && prevTest.AppendedErrorOutput == false {
test = prevTest
} else {
test = curTest
test = curTest
}
if test.isParentTest == false {
test.Message += message
test.AppendedErrorOutput = isErrorOutput(message)
test.AppendedErrorOutput = isErrorOutput(message)
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const (
type Test struct {
Name, Time, Message string
Status Status
AppendedErrorOutput bool
isParentTest bool
AppendedErrorOutput bool
isParentTest bool
}

// Suite of tests (found in some unit testing frameworks)
Expand Down
30 changes: 29 additions & 1 deletion lib/xmlout.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,24 @@ const (
{{end}}
</assembly>
`

// SGTDTemplate is XML template for Sonar Generic Test Data style reporting
// https://docs.sonarqube.org/display/SONAR/Generic+Test+Data
SGTDTemplate string = `<testExecutions version="1">{{range $suite := .Suites}}
{{range $test := $suite.Tests}} <file path="{{testFilePath $suite $test ""}}">
<testCase name="{{$test.Name | escape}}" duration="{{secondsToMilliseconds $test.Time}}"
{{- if and (ne $test.Status $.Skipped) (ne $test.Status $.Failed)}} />{{else}}>
{{- if eq $test.Status $.Skipped }}
<skipped message="">
<![CDATA[{{$test.Message}}]]>
</skipped>{{end}}
{{- if eq $test.Status $.Failed }}
<failure message="error">
<![CDATA[{{$test.Message}}]]>
</failure>{{end}}
</testCase>{{end}}
</file>
{{end}}{{end}}</testExecutions>`
)

// TestResults is passed to XML template
Expand Down Expand Up @@ -104,6 +122,14 @@ func escapeForXML(in string) (string, error) {
return w.String(), nil
}

func secondsToMilliseconds(seconds string) string {
t, err := time.ParseDuration(seconds + "s")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you already know it's in seconds, why not just do the math directly?

if err != nil {
return "0"
}
return strconv.Itoa(int(t.Nanoseconds() / int64(time.Millisecond)))
}

// WriteXML exits xunit XML of tests to out
func WriteXML(suites []*Suite, out io.Writer, xmlTemplate string, testTime time.Time) {
testsResult := TestResults{
Expand All @@ -117,7 +143,9 @@ func WriteXML(suites []*Suite, out io.Writer, xmlTemplate string, testTime time.
}
testsResult.calcTotals()
t := template.New("test template").Funcs(template.FuncMap{
"escape": escapeForXML,
"escape": escapeForXML,
"testFilePath": tmplFuncFilePathForTest,
"secondsToMilliseconds": secondsToMilliseconds,
})

t, err := t.Parse(xml.Header + xmlTemplate)
Expand Down
4 changes: 3 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ func main() {
}

xmlTemplate := lib.XUnitTemplate
if args.xunitnetOut {
if args.sonarGTDOut {
xmlTemplate = lib.SGTDTemplate
} else if args.xunitnetOut {
xmlTemplate = lib.XUnitNetTemplate
} else if args.bambooOut || (len(suites) > 1) {
xmlTemplate = lib.XMLMultiTemplate
Expand Down