1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/*
JUnit XML Reporter for Ginkgo
For usage instructions: http://onsi.github.io/ginkgo/#generating_junit_xml_output
*/
package reporters
import (
"encoding/xml"
"fmt"
"github.com/onsi/ginkgo/config"
"github.com/onsi/ginkgo/types"
"os"
"strings"
)
type JUnitTestSuite struct {
XMLName xml.Name `xml:"testsuite"`
TestCases []JUnitTestCase `xml:"testcase"`
Tests int `xml:"tests,attr"`
Failures int `xml:"failures,attr"`
Time float64 `xml:"time,attr"`
}
type JUnitTestCase struct {
Name string `xml:"name,attr"`
ClassName string `xml:"classname,attr"`
FailureMessage *JUnitFailureMessage `xml:"failure,omitempty"`
Skipped *JUnitSkipped `xml:"skipped,omitempty"`
Time float64 `xml:"time,attr"`
}
type JUnitFailureMessage struct {
Type string `xml:"type,attr"`
Message string `xml:",chardata"`
}
type JUnitSkipped struct {
XMLName xml.Name `xml:"skipped"`
}
type JUnitReporter struct {
suite JUnitTestSuite
filename string
testSuiteName string
}
//NewJUnitReporter creates a new JUnit XML reporter. The XML will be stored in the passed in filename.
func NewJUnitReporter(filename string) *JUnitReporter {
return &JUnitReporter{
filename: filename,
}
}
func (reporter *JUnitReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
reporter.suite = JUnitTestSuite{
Tests: summary.NumberOfSpecsThatWillBeRun,
TestCases: []JUnitTestCase{},
}
reporter.testSuiteName = summary.SuiteDescription
}
func (reporter *JUnitReporter) SpecWillRun(specSummary *types.SpecSummary) {
}
func (reporter *JUnitReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
reporter.handleSetupSummary("BeforeSuite", setupSummary)
}
func (reporter *JUnitReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
reporter.handleSetupSummary("AfterSuite", setupSummary)
}
func failureMessage(failure types.SpecFailure) string {
return fmt.Sprintf("%s\n%s\n%s", failure.ComponentCodeLocation.String(), failure.Message, failure.Location.String())
}
func (reporter *JUnitReporter) handleSetupSummary(name string, setupSummary *types.SetupSummary) {
if setupSummary.State != types.SpecStatePassed {
testCase := JUnitTestCase{
Name: name,
ClassName: reporter.testSuiteName,
}
testCase.FailureMessage = &JUnitFailureMessage{
Type: reporter.failureTypeForState(setupSummary.State),
Message: failureMessage(setupSummary.Failure),
}
testCase.Time = setupSummary.RunTime.Seconds()
reporter.suite.TestCases = append(reporter.suite.TestCases, testCase)
}
}
func (reporter *JUnitReporter) SpecDidComplete(specSummary *types.SpecSummary) {
testCase := JUnitTestCase{
Name: strings.Join(specSummary.ComponentTexts[1:], " "),
ClassName: reporter.testSuiteName,
}
if specSummary.State == types.SpecStateFailed || specSummary.State == types.SpecStateTimedOut || specSummary.State == types.SpecStatePanicked {
testCase.FailureMessage = &JUnitFailureMessage{
Type: reporter.failureTypeForState(specSummary.State),
Message: failureMessage(specSummary.Failure),
}
}
if specSummary.State == types.SpecStateSkipped || specSummary.State == types.SpecStatePending {
testCase.Skipped = &JUnitSkipped{}
}
testCase.Time = specSummary.RunTime.Seconds()
reporter.suite.TestCases = append(reporter.suite.TestCases, testCase)
}
func (reporter *JUnitReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
reporter.suite.Time = summary.RunTime.Seconds()
reporter.suite.Failures = summary.NumberOfFailedSpecs
file, err := os.Create(reporter.filename)
if err != nil {
fmt.Printf("Failed to create JUnit report file: %s\n\t%s", reporter.filename, err.Error())
}
defer file.Close()
file.WriteString(xml.Header)
encoder := xml.NewEncoder(file)
encoder.Indent(" ", " ")
err = encoder.Encode(reporter.suite)
if err != nil {
fmt.Printf("Failed to generate JUnit report\n\t%s", err.Error())
}
}
func (reporter *JUnitReporter) failureTypeForState(state types.SpecState) string {
switch state {
case types.SpecStateFailed:
return "Failure"
case types.SpecStateTimedOut:
return "Timeout"
case types.SpecStatePanicked:
return "Panic"
default:
return ""
}
}
|