forked from knative/pkg
/
junit.go
142 lines (121 loc) · 4.38 KB
/
junit.go
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
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// junit.go defines types and functions specific to manipulating junit test result XML files
package junit
import (
"encoding/xml"
"fmt"
)
// TestStatusEnum is a enum for test result status
type TestStatusEnum string
const (
// Failed means junit test failed
Failed TestStatusEnum = "failed"
// Skipped means junit test skipped
Skipped TestStatusEnum = "skipped"
// Passed means junit test passed
Passed TestStatusEnum = "passed"
)
// TestSuites holds a <testSuites/> list of TestSuite results
type TestSuites struct {
XMLName xml.Name `xml:"testsuites"`
Suites []TestSuite `xml:"testsuite"`
}
// TestSuite holds <testSuite/> results
type TestSuite struct {
XMLName xml.Name `xml:"testsuite"`
Name string `xml:"name,attr"`
Time float64 `xml:"time,attr"` // Seconds
Failures int `xml:"failures,attr"`
Tests int `xml:"tests,attr"`
TestCases []TestCase `xml:"testcase"`
Properties TestProperties `xml:"properties"`
}
// TestCase holds <testcase/> results
type TestCase struct {
Name string `xml:"name,attr"`
Time float64 `xml:"time,attr"` // Seconds
ClassName string `xml:"classname,attr"`
Failure *string `xml:"failure,omitempty"`
Output *string `xml:"system-out,omitempty"`
Error *string `xml:"system-err,omitempty"`
Skipped *string `xml:"skipped,omitempty"`
Properties TestProperties `xml:"properties"`
}
// TestProperties is an array of test properties
type TestProperties struct {
Properties []TestProperty `xml:"property"`
}
// TestProperty defines a property of the test
type TestProperty struct {
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
}
// GetTestStatus returns the test status as a string
func (testCase *TestCase) GetTestStatus() TestStatusEnum {
testStatus := Passed
switch {
case testCase.Failure != nil:
testStatus = Failed
case testCase.Skipped != nil:
testStatus = Skipped
}
return testStatus
}
// AddProperty adds property to testcase
func (testCase *TestCase) AddProperty(name, val string) {
property := TestProperty{Name: name, Value: val}
testCase.Properties.Properties = append(testCase.Properties.Properties, property)
}
// AddTestCase adds a testcase to the testsuite
func (ts *TestSuite) AddTestCase(tc TestCase) {
ts.TestCases = append(ts.TestCases, tc)
}
// GetTestSuite gets TestSuite struct by name
func (testSuites *TestSuites) GetTestSuite(suiteName string) (*TestSuite, error) {
for _, testSuite := range testSuites.Suites {
if testSuite.Name == suiteName {
return &testSuite, nil
}
}
return nil, fmt.Errorf("Test suite '%s' not found", suiteName)
}
// AddTestSuite adds TestSuite to TestSuites
func (testSuites *TestSuites) AddTestSuite(testSuite *TestSuite) error {
if _, err := testSuites.GetTestSuite(testSuite.Name); err == nil {
return fmt.Errorf("Test suite '%s' already exists", testSuite.Name)
}
testSuites.Suites = append(testSuites.Suites, *testSuite)
return nil
}
// ToBytes converts TestSuites struct to bytes array
func (testSuites *TestSuites) ToBytes(prefix, indent string) ([]byte, error) {
return xml.MarshalIndent(testSuites, prefix, indent)
}
// UnMarshal converts bytes array to TestSuites struct,
// it works with both TestSuites and TestSuite structs, if
// input is a TestSuite struct it will still return a TestSuites
// struct, which is an empty wrapper TestSuites containing only
// the input Suite
func UnMarshal(buf []byte) (*TestSuites, error) {
var testSuites TestSuites
if err := xml.Unmarshal(buf, &testSuites); err == nil {
return &testSuites, nil
}
// The input might be a TestSuite if reach here, try parsing with TestSuite
testSuites.Suites = append([]TestSuite(nil), TestSuite{})
if err := xml.Unmarshal(buf, &testSuites.Suites[0]); err != nil {
return nil, err
}
return &testSuites, nil
}