mirror of
https://github.com/jstemmer/go-junit-report.git
synced 2025-04-05 05:00:15 -05:00
Extract and report coverage information.
When `go test` is run on multiple packages and with coverage collection enabled, it appends coverage information to the final result line for each package. With this change, properly handle this additional information and add it into the JUnit XML report as a property of the test suite.
This commit is contained in:
parent
38eb577ca2
commit
6087bd544c
@ -260,6 +260,73 @@ var testCases = []TestCase{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "09-coverage.txt",
|
||||
reportName: "09-report.xml",
|
||||
report: &Report{
|
||||
Packages: []Package{
|
||||
{
|
||||
Name: "package/name",
|
||||
Time: 160,
|
||||
Tests: []*Test{
|
||||
{
|
||||
Name: "TestZ",
|
||||
Time: 60,
|
||||
Result: PASS,
|
||||
Output: []string{},
|
||||
},
|
||||
{
|
||||
Name: "TestA",
|
||||
Time: 100,
|
||||
Result: PASS,
|
||||
Output: []string{},
|
||||
},
|
||||
},
|
||||
CoveragePct: "13.37",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "10-multipkg-coverage.txt",
|
||||
reportName: "10-report.xml",
|
||||
report: &Report{
|
||||
Packages: []Package{
|
||||
{
|
||||
Name: "package1/foo",
|
||||
Time: 400,
|
||||
Tests: []*Test{
|
||||
{
|
||||
Name: "TestA",
|
||||
Time: 100,
|
||||
Result: PASS,
|
||||
Output: []string{},
|
||||
},
|
||||
{
|
||||
Name: "TestB",
|
||||
Time: 300,
|
||||
Result: PASS,
|
||||
Output: []string{},
|
||||
},
|
||||
},
|
||||
CoveragePct: "10.0",
|
||||
},
|
||||
{
|
||||
Name: "package2/bar",
|
||||
Time: 4200,
|
||||
Tests: []*Test{
|
||||
{
|
||||
Name: "TestC",
|
||||
Time: 4200,
|
||||
Result: PASS,
|
||||
Output: []string{},
|
||||
},
|
||||
},
|
||||
CoveragePct: "99.8",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestParser(t *testing.T) {
|
||||
@ -321,6 +388,9 @@ func TestParser(t *testing.T) {
|
||||
t.Errorf("Test.Output ==\n%s\n, want\n%s", testOutput, expTestOutput)
|
||||
}
|
||||
}
|
||||
if pkg.CoveragePct != expPkg.CoveragePct {
|
||||
t.Errorf("Package.CoveragePct == %s, want %s", pkg.CoveragePct, expPkg.CoveragePct)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,9 @@ func JUnitReportXML(report *Report, noXMLHeader bool, w io.Writer) error {
|
||||
|
||||
// properties
|
||||
ts.Properties = append(ts.Properties, JUnitProperty{"go.version", runtime.Version()})
|
||||
if pkg.CoveragePct != "" {
|
||||
ts.Properties = append(ts.Properties, JUnitProperty{"coverage.statements.pct", pkg.CoveragePct})
|
||||
}
|
||||
|
||||
// individual test cases
|
||||
for _, test := range pkg.Tests {
|
||||
|
38
parser.go
38
parser.go
@ -25,9 +25,10 @@ type Report struct {
|
||||
|
||||
// Package contains the test results of a single package.
|
||||
type Package struct {
|
||||
Name string
|
||||
Time int
|
||||
Tests []*Test
|
||||
Name string
|
||||
Time int
|
||||
Tests []*Test
|
||||
CoveragePct string
|
||||
}
|
||||
|
||||
// Test contains the results of a single test.
|
||||
@ -39,8 +40,9 @@ type Test struct {
|
||||
}
|
||||
|
||||
var (
|
||||
regexStatus = regexp.MustCompile(`^--- (PASS|FAIL|SKIP): (.+) \((\d+\.\d+)(?: seconds|s)\)$`)
|
||||
regexResult = regexp.MustCompile(`^(ok|FAIL)\s+(.+)\s(\d+\.\d+)s$`)
|
||||
regexStatus = regexp.MustCompile(`^--- (PASS|FAIL|SKIP): (.+) \((\d+\.\d+)(?: seconds|s)\)$`)
|
||||
regexCoverage = regexp.MustCompile(`^coverage:\s+(\d+\.\d+)%\s+of\s+statements$`)
|
||||
regexResult = regexp.MustCompile(`^(ok|FAIL)\s+(.+)\s(\d+\.\d+)s(?:\s+coverage:\s+(\d+\.\d+)%\s+of\s+statements)?$`)
|
||||
)
|
||||
|
||||
// Parse parses go test output from reader r and returns a report with the
|
||||
@ -60,6 +62,9 @@ func Parse(r io.Reader, pkgName string) (*Report, error) {
|
||||
// current test
|
||||
var cur string
|
||||
|
||||
// coverage percentage report for current package
|
||||
var coveragePct string
|
||||
|
||||
// parse lines
|
||||
for {
|
||||
l, _, err := reader.ReadLine()
|
||||
@ -79,15 +84,21 @@ func Parse(r io.Reader, pkgName string) (*Report, error) {
|
||||
Result: FAIL,
|
||||
Output: make([]string, 0),
|
||||
})
|
||||
} else if matches := regexResult.FindStringSubmatch(line); len(matches) == 4 {
|
||||
} else if matches := regexResult.FindStringSubmatch(line); len(matches) == 5 {
|
||||
if matches[4] != "" {
|
||||
coveragePct = matches[4]
|
||||
}
|
||||
|
||||
// all tests in this package are finished
|
||||
report.Packages = append(report.Packages, Package{
|
||||
Name: matches[2],
|
||||
Time: parseTime(matches[3]),
|
||||
Tests: tests,
|
||||
Name: matches[2],
|
||||
Time: parseTime(matches[3]),
|
||||
Tests: tests,
|
||||
CoveragePct: coveragePct,
|
||||
})
|
||||
|
||||
tests = make([]*Test, 0)
|
||||
coveragePct = ""
|
||||
cur = ""
|
||||
testsTime = 0
|
||||
} else if matches := regexStatus.FindStringSubmatch(line); len(matches) == 4 {
|
||||
@ -110,6 +121,8 @@ func Parse(r io.Reader, pkgName string) (*Report, error) {
|
||||
testTime := parseTime(matches[3]) * 10
|
||||
test.Time = testTime
|
||||
testsTime += testTime
|
||||
} else if matches := regexCoverage.FindStringSubmatch(line); len(matches) == 2 {
|
||||
coveragePct = matches[1]
|
||||
} else if strings.HasPrefix(line, "\t") {
|
||||
// test output
|
||||
test := findTest(tests, cur)
|
||||
@ -123,9 +136,10 @@ func Parse(r io.Reader, pkgName string) (*Report, error) {
|
||||
if len(tests) > 0 {
|
||||
// no result line found
|
||||
report.Packages = append(report.Packages, Package{
|
||||
Name: pkgName,
|
||||
Time: testsTime,
|
||||
Tests: tests,
|
||||
Name: pkgName,
|
||||
Time: testsTime,
|
||||
Tests: tests,
|
||||
CoveragePct: coveragePct,
|
||||
})
|
||||
}
|
||||
|
||||
|
7
tests/09-coverage.txt
Normal file
7
tests/09-coverage.txt
Normal file
@ -0,0 +1,7 @@
|
||||
=== RUN TestZ
|
||||
--- PASS: TestZ (0.06 seconds)
|
||||
=== RUN TestA
|
||||
--- PASS: TestA (0.10 seconds)
|
||||
PASS
|
||||
coverage: 13.37% of statements
|
||||
ok package/name 0.160s
|
11
tests/09-report.xml
Normal file
11
tests/09-report.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites>
|
||||
<testsuite tests="2" failures="0" time="0.160" name="package/name">
|
||||
<properties>
|
||||
<property name="go.version" value="1.0"></property>
|
||||
<property name="coverage.statements.pct" value="13.37"></property>
|
||||
</properties>
|
||||
<testcase classname="name" name="TestZ" time="0.060"></testcase>
|
||||
<testcase classname="name" name="TestA" time="0.100"></testcase>
|
||||
</testsuite>
|
||||
</testsuites>
|
12
tests/10-multipkg-coverage.txt
Normal file
12
tests/10-multipkg-coverage.txt
Normal file
@ -0,0 +1,12 @@
|
||||
=== RUN TestA
|
||||
--- PASS: TestA (0.10 seconds)
|
||||
=== RUN TestB
|
||||
--- PASS: TestB (0.30 seconds)
|
||||
PASS
|
||||
coverage: 10% of statements
|
||||
ok package1/foo 0.400s coverage: 10.0% of statements
|
||||
=== RUN TestC
|
||||
--- PASS: TestC (4.20 seconds)
|
||||
PASS
|
||||
coverage: 99.8% of statements
|
||||
ok package2/bar 4.200s coverage: 99.8% of statements
|
18
tests/10-report.xml
Normal file
18
tests/10-report.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites>
|
||||
<testsuite tests="2" failures="0" time="0.400" name="package1/foo">
|
||||
<properties>
|
||||
<property name="go.version" value="go1.4.2"></property>
|
||||
<property name="coverage.statements.pct" value="10.0"></property>
|
||||
</properties>
|
||||
<testcase classname="foo" name="TestA" time="0.100"></testcase>
|
||||
<testcase classname="foo" name="TestB" time="0.300"></testcase>
|
||||
</testsuite>
|
||||
<testsuite tests="1" failures="0" time="4.200" name="package2/bar">
|
||||
<properties>
|
||||
<property name="go.version" value="go1.4.2"></property>
|
||||
<property name="coverage.statements.pct" value="99.8"></property>
|
||||
</properties>
|
||||
<testcase classname="bar" name="TestC" time="4.200"></testcase>
|
||||
</testsuite>
|
||||
</testsuites>
|
Loading…
x
Reference in New Issue
Block a user