@@ -6,97 +6,82 @@ import (
6
6
"github.com/openshift/origin/tools/junitreport/pkg/api"
7
7
)
8
8
9
- func newTestDataParser () testDataParser {
10
- return testDataParser {
11
- // testStartPattern matches the line in verbose `go test` output that marks the declaration of a test.
12
- // The first submatch of this regex is the name of the test
13
- testStartPattern : regexp .MustCompile (`=== RUN\s+([^/]+)$` ),
9
+ // testStartPattern matches the line in verbose `go test` output that marks the declaration of a test.
10
+ // The first submatch of this regex is the name of the test
11
+ var testStartPattern = regexp .MustCompile (`^=== RUN\s+([^\s]+)$` )
14
12
15
- // testResultPattern matches the line in verbose `go test` output that marks the result of a test.
16
- // The first submatch of this regex is the result of the test (PASS, FAIL, or SKIP)
17
- // The second submatch of this regex is the name of the test
18
- // The third submatch of this regex is the time taken in seconds for the test to finish
19
- testResultPattern : regexp .MustCompile (`--- (PASS|FAIL|SKIP):\s+([^/]+)\s+\((\d+\.\d+)(s| seconds)\)` ),
20
- }
21
- }
22
-
23
- type testDataParser struct {
24
- testStartPattern * regexp.Regexp
25
- testResultPattern * regexp.Regexp
26
- }
27
-
28
- // MarksBeginning determines if the line marks the beginning of a test case
29
- func (p * testDataParser ) MarksBeginning (line string ) bool {
30
- return p .testStartPattern .MatchString (line )
31
- }
32
-
33
- // ExtractName extracts the name of the test case from test output line
34
- func (p * testDataParser ) ExtractName (line string ) (string , bool ) {
35
- if matches := p .testStartPattern .FindStringSubmatch (line ); len (matches ) > 1 && len (matches [1 ]) > 0 {
13
+ // ExtractRun identifies the start of a test output section.
14
+ func ExtractRun (line string ) (string , bool ) {
15
+ if matches := testStartPattern .FindStringSubmatch (line ); len (matches ) > 1 && len (matches [1 ]) > 0 {
36
16
return matches [1 ], true
37
17
}
38
-
39
- if matches := p .testResultPattern .FindStringSubmatch (line ); len (matches ) > 2 && len (matches [2 ]) > 0 {
40
- return matches [2 ], true
41
- }
42
-
43
18
return "" , false
44
19
}
45
20
46
- // ExtractResult extracts the test result from a test output line
47
- func (p * testDataParser ) ExtractResult (line string ) (api.TestResult , bool ) {
48
- if matches := p .testResultPattern .FindStringSubmatch (line ); len (matches ) > 1 && len (matches [1 ]) > 0 {
49
- switch matches [1 ] {
21
+ // testResultPattern matches the line in verbose `go test` output that marks the result of a test.
22
+ // The first submatch of this regex is the result of the test (PASS, FAIL, or SKIP)
23
+ // The second submatch of this regex is the name of the test
24
+ // The third submatch of this regex is the time taken in seconds for the test to finish
25
+ var testResultPattern = regexp .MustCompile (`^(\s*)--- (PASS|FAIL|SKIP):\s+([^\s]+)\s+\((\d+\.\d+)(s| seconds)\)$` )
26
+
27
+ // ExtractResult extracts the test result from a test output line. Depth is measured as the leading whitespace
28
+ // for the line multiplied by four, which is used to identify output from nested Go subtests.
29
+ func ExtractResult (line string ) (r api.TestResult , name string , depth int , duration string , ok bool ) {
30
+ if matches := testResultPattern .FindStringSubmatch (line ); len (matches ) > 1 && len (matches [2 ]) > 0 {
31
+ switch matches [2 ] {
50
32
case "PASS" :
51
- return api .TestResultPass , true
33
+ r = api .TestResultPass
52
34
case "SKIP" :
53
- return api .TestResultSkip , true
35
+ r = api .TestResultSkip
54
36
case "FAIL" :
55
- return api .TestResultFail , true
37
+ r = api .TestResultFail
38
+ default :
39
+ return "" , "" , 0 , "" , false
56
40
}
41
+ name = matches [3 ]
42
+ duration = matches [4 ] + "s"
43
+ depth = len (matches [1 ]) / 4
44
+ ok = true
45
+ return
57
46
}
58
- return "" , false
59
- }
60
-
61
- // ExtractDuration extracts the test duration from a test output line
62
- func (p * testDataParser ) ExtractDuration (line string ) (string , bool ) {
63
- if matches := p .testResultPattern .FindStringSubmatch (line ); len (matches ) > 3 && len (matches [3 ]) > 0 {
64
- return matches [3 ] + "s" , true
65
- }
66
- return "" , false
47
+ return "" , "" , 0 , "" , false
67
48
}
68
49
69
- func newTestSuiteDataParser () testSuiteDataParser {
70
- return testSuiteDataParser {
71
- // coverageOutputPattern matches coverage output on a single line.
72
- // The first submatch of this regex is the percent coverage
73
- coverageOutputPattern : regexp .MustCompile (`coverage:\s+(\d+\.\d+)\% of statements` ),
50
+ // testOutputPattern captures a line with leading whitespace.
51
+ var testOutputPattern = regexp .MustCompile (`^(\s*)(.*)$` )
74
52
75
- // packageResultPattern matches the `go test` output for the end of a package.
76
- // The first submatch of this regex matches the result of the test (ok or FAIL)
77
- // The second submatch of this regex matches the name of the package
78
- // The third submatch of this regex matches the time taken in seconds for tests in the package to finish
79
- // The sixth (optional) submatch of this regex is the percent coverage
80
- packageResultPattern : regexp . MustCompile ( `(ok|FAIL)\s+(.+)[\s\t]+(\d+\.\d+(s| seconds))([\s\t]+coverage:\s+(\d+\.\d+)\% of statements)?` ),
53
+ // ExtractOutput captures a line of output indented by whitespace and returns
54
+ // the output, the indentation depth (4 spaces is the canonical indentation used by go test),
55
+ // and whether the match was successful.
56
+ func ExtractOutput ( line string ) ( string , int , bool ) {
57
+ if matches := testOutputPattern . FindStringSubmatch ( line ); len ( matches ) > 1 {
58
+ return matches [ 2 ], len ( matches [ 1 ]) / 4 , true
81
59
}
60
+ return "" , 0 , false
82
61
}
83
62
84
- type testSuiteDataParser struct {
85
- coverageOutputPattern * regexp.Regexp
86
- packageResultPattern * regexp.Regexp
87
- }
88
-
89
- // ExtractName extracts the name of the test suite from a test output line
90
- func (p * testSuiteDataParser ) ExtractName (line string ) (string , bool ) {
91
- if matches := p .packageResultPattern .FindStringSubmatch (line ); len (matches ) > 2 && len (matches [2 ]) > 0 {
92
- return matches [2 ], true
63
+ // coverageOutputPattern matches coverage output on a single line.
64
+ // The first submatch of this regex is the percent coverage
65
+ var coverageOutputPattern = regexp .MustCompile (`coverage:\s+(\d+\.\d+)\% of statements` )
66
+
67
+ // packageResultPattern matches the `go test` output for the end of a package.
68
+ // The first submatch of this regex matches the result of the test (ok or FAIL)
69
+ // The second submatch of this regex matches the name of the package
70
+ // The third submatch of this regex matches the time taken in seconds for tests in the package to finish
71
+ // The sixth (optional) submatch of this regex is the percent coverage
72
+ var packageResultPattern = regexp .MustCompile (`^(ok|FAIL)\s+(.+)[\s\t]+(\d+\.\d+(s| seconds))([\s\t]+coverage:\s+(\d+\.\d+)\% of statements)?$` )
73
+
74
+ // ExtractPackage extracts the name of the test suite from a test package line.
75
+ func ExtractPackage (line string ) (name string , duration string , coverage string , ok bool ) {
76
+ if matches := packageResultPattern .FindStringSubmatch (line ); len (matches ) > 1 && len (matches [2 ]) > 0 {
77
+ return matches [2 ], matches [3 ], matches [5 ], true
93
78
}
94
- return "" , false
79
+ return "" , "" , "" , false
95
80
}
96
81
97
82
// ExtractDuration extracts the package duration from a test output line
98
- func ( p * testSuiteDataParser ) ExtractDuration (line string ) (string , bool ) {
99
- if resultMatches := p . packageResultPattern .FindStringSubmatch (line ); len (resultMatches ) > 3 && len (resultMatches [3 ]) > 0 {
83
+ func ExtractDuration (line string ) (string , bool ) {
84
+ if resultMatches := packageResultPattern .FindStringSubmatch (line ); len (resultMatches ) > 3 && len (resultMatches [3 ]) > 0 {
100
85
return resultMatches [3 ], true
101
86
}
102
87
return "" , false
@@ -107,24 +92,19 @@ const (
107
92
)
108
93
109
94
// ExtractProperties extracts any metadata properties of the test suite from a test output line
110
- func ( p * testSuiteDataParser ) ExtractProperties (line string ) (map [string ]string , bool ) {
95
+ func ExtractProperties (line string ) (map [string ]string , bool ) {
111
96
// the only test suite properties that Go testing can create are coverage values, which can either
112
97
// be present on their own line or in the package result line
113
- if matches := p . coverageOutputPattern .FindStringSubmatch (line ); len (matches ) > 1 && len (matches [1 ]) > 0 {
98
+ if matches := coverageOutputPattern .FindStringSubmatch (line ); len (matches ) > 1 && len (matches [1 ]) > 0 {
114
99
return map [string ]string {
115
100
coveragePropertyName : matches [1 ],
116
101
}, true
117
102
}
118
103
119
- if resultMatches := p . packageResultPattern .FindStringSubmatch (line ); len (resultMatches ) > 6 && len (resultMatches [6 ]) > 0 {
104
+ if resultMatches := packageResultPattern .FindStringSubmatch (line ); len (resultMatches ) > 6 && len (resultMatches [6 ]) > 0 {
120
105
return map [string ]string {
121
106
coveragePropertyName : resultMatches [6 ],
122
107
}, true
123
108
}
124
109
return map [string ]string {}, false
125
110
}
126
-
127
- // MarksCompletion determines if the line marks the completion of a test suite
128
- func (p * testSuiteDataParser ) MarksCompletion (line string ) bool {
129
- return p .packageResultPattern .MatchString (line )
130
- }
0 commit comments