mirror of
https://github.com/jstemmer/go-junit-report.git
synced 2025-04-06 21:48:08 -05:00
Adds ability to parse benchmarking information, and (optional) with memory information and with -count specified. Includes a number of unit tests. Issue #70.
This commit is contained in:
parent
1ce4b93a20
commit
b2f467b67c
17
README.md
17
README.md
@ -15,6 +15,17 @@ command:
|
|||||||
go get -u github.com/jstemmer/go-junit-report
|
go get -u github.com/jstemmer/go-junit-report
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Contribution
|
||||||
|
|
||||||
|
Create an Issue and discuss the fix or feature, then fork the package.
|
||||||
|
Clone to github.com/jstemmer/go-junit-report. This is necessary because go import uses this path.
|
||||||
|
Fix or implement feature. Test and then commit change.
|
||||||
|
Specify #Issue and describe change in the commit message.
|
||||||
|
Create Pull Request. It can be merged by owner or administrator then.
|
||||||
|
|
||||||
|
## Run Tests
|
||||||
|
go test
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
go-junit-report reads the `go test` verbose output from standard in and writes
|
go-junit-report reads the `go test` verbose output from standard in and writes
|
||||||
@ -24,6 +35,12 @@ junit compatible XML to standard out.
|
|||||||
go test -v 2>&1 | go-junit-report > report.xml
|
go test -v 2>&1 | go-junit-report > report.xml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that it also can parse benchmark output with `-bench` flag:
|
||||||
|
```bash
|
||||||
|
go test -bench . -benchmem -count 100
|
||||||
|
```
|
||||||
|
will return the average mean benchmark time as the test case time.
|
||||||
|
|
||||||
[travis-badge]: https://travis-ci.org/jstemmer/go-junit-report.svg
|
[travis-badge]: https://travis-ci.org/jstemmer/go-junit-report.svg
|
||||||
[travis-link]: https://travis-ci.org/jstemmer/go-junit-report
|
[travis-link]: https://travis-ci.org/jstemmer/go-junit-report
|
||||||
[report-badge]: https://goreportcard.com/badge/github.com/jstemmer/go-junit-report
|
[report-badge]: https://goreportcard.com/badge/github.com/jstemmer/go-junit-report
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -38,6 +39,9 @@ type JUnitTestCase struct {
|
|||||||
Time string `xml:"time,attr"`
|
Time string `xml:"time,attr"`
|
||||||
SkipMessage *JUnitSkipMessage `xml:"skipped,omitempty"`
|
SkipMessage *JUnitSkipMessage `xml:"skipped,omitempty"`
|
||||||
Failure *JUnitFailure `xml:"failure,omitempty"`
|
Failure *JUnitFailure `xml:"failure,omitempty"`
|
||||||
|
// for benchmarks
|
||||||
|
Bytes string `xml:"bytes,attr,omitempty"`
|
||||||
|
Allocs string `xml:"allocs,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JUnitSkipMessage contains the reason why a testcase was skipped.
|
// JUnitSkipMessage contains the reason why a testcase was skipped.
|
||||||
@ -65,8 +69,17 @@ func JUnitReportXML(report *parser.Report, noXMLHeader bool, goVersion string, w
|
|||||||
|
|
||||||
// convert Report to JUnit test suites
|
// convert Report to JUnit test suites
|
||||||
for _, pkg := range report.Packages {
|
for _, pkg := range report.Packages {
|
||||||
|
var tests int
|
||||||
|
if len(pkg.Tests) >= 1 && len(pkg.Benchmarks) >= 1 {
|
||||||
|
tests = len(pkg.Tests) + len(pkg.Benchmarks)
|
||||||
|
} else if len(pkg.Benchmarks) >= 1 {
|
||||||
|
tests = len(pkg.Benchmarks)
|
||||||
|
} else {
|
||||||
|
tests = len(pkg.Tests)
|
||||||
|
}
|
||||||
|
|
||||||
ts := JUnitTestSuite{
|
ts := JUnitTestSuite{
|
||||||
Tests: len(pkg.Tests),
|
Tests: tests,
|
||||||
Failures: 0,
|
Failures: 0,
|
||||||
Time: formatTime(pkg.Duration),
|
Time: formatTime(pkg.Duration),
|
||||||
Name: pkg.Name,
|
Name: pkg.Name,
|
||||||
@ -114,6 +127,25 @@ func JUnitReportXML(report *parser.Report, noXMLHeader bool, goVersion string, w
|
|||||||
ts.TestCases = append(ts.TestCases, testCase)
|
ts.TestCases = append(ts.TestCases, testCase)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// individual benchmarks
|
||||||
|
for _, benchmark := range pkg.Benchmarks {
|
||||||
|
benchmarkCase := JUnitTestCase{
|
||||||
|
Classname: classname,
|
||||||
|
Name: benchmark.Name,
|
||||||
|
Time: formatBenchmarkTime(benchmark.Duration),
|
||||||
|
Failure: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
if benchmark.Bytes != 0 {
|
||||||
|
benchmarkCase.Bytes = strconv.Itoa(benchmark.Bytes)
|
||||||
|
}
|
||||||
|
if benchmark.Allocs != 0 {
|
||||||
|
benchmarkCase.Allocs = strconv.Itoa(benchmark.Allocs)
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.TestCases = append(ts.TestCases, benchmarkCase)
|
||||||
|
}
|
||||||
|
|
||||||
suites.Suites = append(suites.Suites, ts)
|
suites.Suites = append(suites.Suites, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,3 +171,7 @@ func JUnitReportXML(report *parser.Report, noXMLHeader bool, goVersion string, w
|
|||||||
func formatTime(d time.Duration) string {
|
func formatTime(d time.Duration) string {
|
||||||
return fmt.Sprintf("%.3f", d.Seconds())
|
return fmt.Sprintf("%.3f", d.Seconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatBenchmarkTime(d time.Duration) string {
|
||||||
|
return fmt.Sprintf("%.9f", d.Seconds())
|
||||||
|
}
|
||||||
|
@ -919,6 +919,246 @@ var testCases = []TestCase{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "22-bench.txt",
|
||||||
|
reportName: "22-report.xml",
|
||||||
|
report: &parser.Report{
|
||||||
|
Packages: []parser.Package{
|
||||||
|
{
|
||||||
|
Name: "package/basic",
|
||||||
|
Duration: 3212 * time.Millisecond,
|
||||||
|
Time: 3212,
|
||||||
|
Benchmarks: []*parser.Benchmark{
|
||||||
|
{
|
||||||
|
Name: "BenchmarkParse",
|
||||||
|
Duration: 604 * time.Nanosecond,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "BenchmarkReadingList",
|
||||||
|
Duration: 1425 * time.Nanosecond,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "23-benchmem.txt",
|
||||||
|
reportName: "23-report.xml",
|
||||||
|
report: &parser.Report{
|
||||||
|
Packages: []parser.Package{
|
||||||
|
{
|
||||||
|
Name: "package/one",
|
||||||
|
Duration: 9415 * time.Millisecond,
|
||||||
|
Time: 9415,
|
||||||
|
Benchmarks: []*parser.Benchmark{
|
||||||
|
{
|
||||||
|
Name: "BenchmarkIpsHistoryInsert",
|
||||||
|
Duration: 52568 * time.Nanosecond,
|
||||||
|
Bytes: 24879,
|
||||||
|
Allocs: 494,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "BenchmarkIpsHistoryLookup",
|
||||||
|
Duration: 15208 * time.Nanosecond,
|
||||||
|
Bytes: 7369,
|
||||||
|
Allocs: 143,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "24-benchtests.txt",
|
||||||
|
reportName: "24-report.xml",
|
||||||
|
report: &parser.Report{
|
||||||
|
Packages: []parser.Package{
|
||||||
|
{
|
||||||
|
Name: "package3/baz",
|
||||||
|
Duration: 1382 * time.Millisecond,
|
||||||
|
Time: 1382,
|
||||||
|
Tests: []*parser.Test{
|
||||||
|
{
|
||||||
|
Name: "TestNew",
|
||||||
|
Duration: 0,
|
||||||
|
Time: 0,
|
||||||
|
Result: parser.PASS,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "TestNew/no",
|
||||||
|
Duration: 0,
|
||||||
|
Time: 0,
|
||||||
|
Result: parser.PASS,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "TestNew/normal",
|
||||||
|
Duration: 0,
|
||||||
|
Time: 0,
|
||||||
|
Result: parser.PASS,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "TestWriteThis",
|
||||||
|
Duration: 0,
|
||||||
|
Time: 0,
|
||||||
|
Result: parser.PASS,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Benchmarks: []*parser.Benchmark{
|
||||||
|
{
|
||||||
|
Name: "BenchmarkDeepMerge",
|
||||||
|
Duration: 2611 * time.Nanosecond,
|
||||||
|
Bytes: 1110,
|
||||||
|
Allocs: 16,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "BenchmarkNext",
|
||||||
|
Duration: 100 * time.Nanosecond,
|
||||||
|
Bytes: 100,
|
||||||
|
Allocs: 1,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "25-benchcount.txt",
|
||||||
|
reportName: "25-report.xml",
|
||||||
|
report: &parser.Report{
|
||||||
|
Packages: []parser.Package{
|
||||||
|
{
|
||||||
|
Name: "pkg/count",
|
||||||
|
Duration: 14211 * time.Millisecond,
|
||||||
|
Time: 14211,
|
||||||
|
Benchmarks: []*parser.Benchmark{
|
||||||
|
{
|
||||||
|
Name: "BenchmarkNew",
|
||||||
|
Duration: 352 * time.Nanosecond,
|
||||||
|
Bytes: 80,
|
||||||
|
Allocs: 3,
|
||||||
|
Count: 5,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "BenchmarkFew",
|
||||||
|
Duration: 102 * time.Nanosecond,
|
||||||
|
Bytes: 20,
|
||||||
|
Allocs: 1,
|
||||||
|
Count: 5,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "26-testbenchmultiple.txt",
|
||||||
|
reportName: "26-report.xml",
|
||||||
|
report: &parser.Report{
|
||||||
|
Packages: []parser.Package{
|
||||||
|
{
|
||||||
|
Name: "multiple/repeating",
|
||||||
|
Duration: 14211 * time.Millisecond,
|
||||||
|
Time: 14211,
|
||||||
|
Tests: []*parser.Test{
|
||||||
|
{
|
||||||
|
Name: "TestRepeat",
|
||||||
|
Duration: 0,
|
||||||
|
Time: 0,
|
||||||
|
Result: parser.PASS,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "TestRepeat",
|
||||||
|
Duration: 0,
|
||||||
|
Time: 0,
|
||||||
|
Result: parser.PASS,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "TestRepeat",
|
||||||
|
Duration: 0,
|
||||||
|
Time: 0,
|
||||||
|
Result: parser.PASS,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "TestRepeat",
|
||||||
|
Duration: 0,
|
||||||
|
Time: 0,
|
||||||
|
Result: parser.PASS,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "TestRepeat",
|
||||||
|
Duration: 0,
|
||||||
|
Time: 0,
|
||||||
|
Result: parser.PASS,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Benchmarks: []*parser.Benchmark{
|
||||||
|
{
|
||||||
|
Name: "BenchmarkNew",
|
||||||
|
Duration: 352 * time.Nanosecond,
|
||||||
|
Bytes: 80,
|
||||||
|
Allocs: 3,
|
||||||
|
Count: 5,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "BenchmarkFew",
|
||||||
|
Duration: 102 * time.Nanosecond,
|
||||||
|
Bytes: 20,
|
||||||
|
Allocs: 1,
|
||||||
|
Count: 5,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "27-benchdecimal.txt",
|
||||||
|
reportName: "27-report.xml",
|
||||||
|
report: &parser.Report{
|
||||||
|
Packages: []parser.Package{
|
||||||
|
{
|
||||||
|
Name: "really/small",
|
||||||
|
Duration: 4344 * time.Millisecond,
|
||||||
|
Time: 4344,
|
||||||
|
Benchmarks: []*parser.Benchmark{
|
||||||
|
{
|
||||||
|
Name: "BenchmarkItsy",
|
||||||
|
Duration: 45 * time.Nanosecond,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "BenchmarkTeeny",
|
||||||
|
Duration: 2 * time.Nanosecond,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "BenchmarkWeeny",
|
||||||
|
Duration: 0 * time.Second,
|
||||||
|
Output: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParser(t *testing.T) {
|
func TestParser(t *testing.T) {
|
||||||
@ -994,6 +1234,37 @@ func TestParser(t *testing.T) {
|
|||||||
t.Errorf("Test.Output (%s) ==\n%s\n, want\n%s", test.Name, testOutput, expTestOutput)
|
t.Errorf("Test.Output (%s) ==\n%s\n, want\n%s", test.Name, testOutput, expTestOutput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(pkg.Benchmarks) != len(expPkg.Benchmarks) {
|
||||||
|
t.Fatalf("Package Benchmarks == %d, want %d", len(pkg.Benchmarks), len(expPkg.Benchmarks))
|
||||||
|
}
|
||||||
|
|
||||||
|
for j, benchmark := range pkg.Benchmarks {
|
||||||
|
expBenchmark := expPkg.Benchmarks[j]
|
||||||
|
|
||||||
|
if benchmark.Name != expBenchmark.Name {
|
||||||
|
t.Errorf("Test.Name == %s, want %s", benchmark.Name, expBenchmark.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if benchmark.Duration != expBenchmark.Duration {
|
||||||
|
t.Errorf("benchmark.Duration == %s, want %s", benchmark.Duration, expBenchmark.Duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
if benchmark.Bytes != expBenchmark.Bytes {
|
||||||
|
t.Errorf("benchmark.Bytes == %d, want %d", benchmark.Bytes, expBenchmark.Bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if benchmark.Allocs != expBenchmark.Allocs {
|
||||||
|
t.Errorf("benchmark.Allocs == %d, want %d", benchmark.Allocs, expBenchmark.Allocs)
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmarkOutput := strings.Join(benchmark.Output, "\n")
|
||||||
|
expBenchmarkOutput := strings.Join(expBenchmark.Output, "\n")
|
||||||
|
if benchmarkOutput != expBenchmarkOutput {
|
||||||
|
t.Errorf("Benchmark.Output (%s) ==\n%s\n, want\n%s", benchmark.Name, benchmarkOutput, expBenchmarkOutput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if pkg.CoveragePct != expPkg.CoveragePct {
|
if pkg.CoveragePct != expPkg.CoveragePct {
|
||||||
t.Errorf("Package.CoveragePct == %s, want %s", pkg.CoveragePct, expPkg.CoveragePct)
|
t.Errorf("Package.CoveragePct == %s, want %s", pkg.CoveragePct, expPkg.CoveragePct)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -28,6 +29,7 @@ type Package struct {
|
|||||||
Name string
|
Name string
|
||||||
Duration time.Duration
|
Duration time.Duration
|
||||||
Tests []*Test
|
Tests []*Test
|
||||||
|
Benchmarks []*Benchmark
|
||||||
CoveragePct string
|
CoveragePct string
|
||||||
|
|
||||||
// Time is deprecated, use Duration instead.
|
// Time is deprecated, use Duration instead.
|
||||||
@ -45,10 +47,25 @@ type Test struct {
|
|||||||
Time int // in milliseconds
|
Time int // in milliseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Benchmark contains the results of a single benchmark.
|
||||||
|
type Benchmark struct {
|
||||||
|
Name string
|
||||||
|
Duration time.Duration
|
||||||
|
// number of B/op
|
||||||
|
Bytes int
|
||||||
|
// number of allocs/op
|
||||||
|
Allocs int
|
||||||
|
// number of times this benchmark has been seen (for averaging).
|
||||||
|
Count int
|
||||||
|
Output []string
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
regexStatus = regexp.MustCompile(`--- (PASS|FAIL|SKIP): (.+) \((\d+\.\d+)(?: seconds|s)\)`)
|
regexStatus = regexp.MustCompile(`--- (PASS|FAIL|SKIP): (.+) \((\d+\.\d+)(?: seconds|s)\)`)
|
||||||
regexCoverage = regexp.MustCompile(`^coverage:\s+(\d+\.\d+)%\s+of\s+statements(?:\sin\s.+)?$`)
|
regexCoverage = regexp.MustCompile(`^coverage:\s+(\d+\.\d+)%\s+of\s+statements(?:\sin\s.+)?$`)
|
||||||
regexResult = regexp.MustCompile(`^(ok|FAIL)\s+([^ ]+)\s+(?:(\d+\.\d+)s|\(cached\)|(\[\w+ failed]))(?:\s+coverage:\s+(\d+\.\d+)%\sof\sstatements(?:\sin\s.+)?)?$`)
|
regexResult = regexp.MustCompile(`^(ok|FAIL)\s+([^ ]+)\s+(?:(\d+\.\d+)s|\(cached\)|(\[\w+ failed]))(?:\s+coverage:\s+(\d+\.\d+)%\sof\sstatements(?:\sin\s.+)?)?$`)
|
||||||
|
// regexBenchmark captures 3-5 groups: benchmark name, number of times ran, ns/op (with or without decimal), B/op (optional), and allocs/op (optional).
|
||||||
|
regexBenchmark = regexp.MustCompile(`^(Benchmark\w+)-\d\s+(\d+)\s+((\d+|\d+\.\d+)\sns/op)(\s+\d+\sB/op)?(\s+\d+\sallocs/op)?`)
|
||||||
regexOutput = regexp.MustCompile(`( )*\t(.*)`)
|
regexOutput = regexp.MustCompile(`( )*\t(.*)`)
|
||||||
regexSummary = regexp.MustCompile(`^(PASS|FAIL|SKIP)$`)
|
regexSummary = regexp.MustCompile(`^(PASS|FAIL|SKIP)$`)
|
||||||
)
|
)
|
||||||
@ -64,10 +81,13 @@ func Parse(r io.Reader, pkgName string) (*Report, error) {
|
|||||||
// keep track of tests we find
|
// keep track of tests we find
|
||||||
var tests []*Test
|
var tests []*Test
|
||||||
|
|
||||||
|
// keep track of benchmarks we find
|
||||||
|
var benchmarks []*Benchmark
|
||||||
|
|
||||||
// sum of tests' time, use this if current test has no result line (when it is compiled test)
|
// sum of tests' time, use this if current test has no result line (when it is compiled test)
|
||||||
var testsTime time.Duration
|
var testsTime time.Duration
|
||||||
|
|
||||||
// current test
|
// current test or benchmark
|
||||||
var cur string
|
var cur string
|
||||||
|
|
||||||
// keep track if we've already seen a summary for the current test
|
// keep track if we've already seen a summary for the current test
|
||||||
@ -108,6 +128,60 @@ func Parse(r io.Reader, pkgName string) (*Report, error) {
|
|||||||
// clear the current build package, so output lines won't be added to that build
|
// clear the current build package, so output lines won't be added to that build
|
||||||
capturedPackage = ""
|
capturedPackage = ""
|
||||||
seenSummary = false
|
seenSummary = false
|
||||||
|
} else if strings.HasPrefix(line, "Benchmark") {
|
||||||
|
// parse benchmarking info
|
||||||
|
matches := regexBenchmark.FindStringSubmatch(line)
|
||||||
|
if len(matches) < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var name string
|
||||||
|
var duration time.Duration
|
||||||
|
var bytes int
|
||||||
|
var allocs int
|
||||||
|
|
||||||
|
for _, field := range matches[1:] {
|
||||||
|
field = strings.TrimSpace(field)
|
||||||
|
if strings.HasPrefix(field, "Benchmark") {
|
||||||
|
name = field
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(field, " ns/op") {
|
||||||
|
durString := strings.TrimSuffix(field, " ns/op")
|
||||||
|
duration = parseNanoseconds(durString)
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(field, " B/op") {
|
||||||
|
b, _ := strconv.Atoi(strings.TrimSuffix(field, " B/op"))
|
||||||
|
bytes = b
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(field, " allocs/op") {
|
||||||
|
a, _ := strconv.Atoi(strings.TrimSuffix(field, " allocs/op"))
|
||||||
|
allocs = a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var duplicate bool
|
||||||
|
// check if duplicate benchmark
|
||||||
|
for _, bench := range benchmarks {
|
||||||
|
if bench.Name == name {
|
||||||
|
duplicate = true
|
||||||
|
bench.Count++
|
||||||
|
bench.Duration += duration
|
||||||
|
bench.Bytes += bytes
|
||||||
|
bench.Allocs += allocs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(benchmarks) < 1 || duplicate == false {
|
||||||
|
// the first time this benchmark has been seen
|
||||||
|
benchmarks = append(benchmarks, &Benchmark{
|
||||||
|
Name: name,
|
||||||
|
Duration: duration,
|
||||||
|
Bytes: bytes,
|
||||||
|
Allocs: allocs,
|
||||||
|
Count: 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
} else if strings.HasPrefix(line, "=== PAUSE ") {
|
} else if strings.HasPrefix(line, "=== PAUSE ") {
|
||||||
continue
|
continue
|
||||||
} else if strings.HasPrefix(line, "=== CONT ") {
|
} else if strings.HasPrefix(line, "=== CONT ") {
|
||||||
@ -137,10 +211,21 @@ func Parse(r io.Reader, pkgName string) (*Report, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// all tests in this package are finished
|
// all tests in this package are finished
|
||||||
|
|
||||||
|
for _, bench := range benchmarks {
|
||||||
|
if bench.Count > 1 {
|
||||||
|
bench.Allocs = bench.Allocs / bench.Count
|
||||||
|
bench.Bytes = bench.Bytes / bench.Count
|
||||||
|
newDuration := bench.Duration / time.Duration(bench.Count)
|
||||||
|
bench.Duration = newDuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
report.Packages = append(report.Packages, Package{
|
report.Packages = append(report.Packages, Package{
|
||||||
Name: matches[2],
|
Name: matches[2],
|
||||||
Duration: parseSeconds(matches[3]),
|
Duration: parseSeconds(matches[3]),
|
||||||
Tests: tests,
|
Tests: tests,
|
||||||
|
Benchmarks: benchmarks,
|
||||||
CoveragePct: coveragePct,
|
CoveragePct: coveragePct,
|
||||||
|
|
||||||
Time: int(parseSeconds(matches[3]) / time.Millisecond), // deprecated
|
Time: int(parseSeconds(matches[3]) / time.Millisecond), // deprecated
|
||||||
@ -206,6 +291,7 @@ func Parse(r io.Reader, pkgName string) (*Report, error) {
|
|||||||
Duration: testsTime,
|
Duration: testsTime,
|
||||||
Time: int(testsTime / time.Millisecond),
|
Time: int(testsTime / time.Millisecond),
|
||||||
Tests: tests,
|
Tests: tests,
|
||||||
|
Benchmarks: benchmarks,
|
||||||
CoveragePct: coveragePct,
|
CoveragePct: coveragePct,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -222,6 +308,16 @@ func parseSeconds(t string) time.Duration {
|
|||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseNanoseconds(t string) time.Duration {
|
||||||
|
// note: if input < 1 ns precision, result will be 0s.
|
||||||
|
if t == "" {
|
||||||
|
return time.Duration(0)
|
||||||
|
}
|
||||||
|
// ignore error
|
||||||
|
d, _ := time.ParseDuration(t + "ns")
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
func findTest(tests []*Test, name string) *Test {
|
func findTest(tests []*Test, name string) *Test {
|
||||||
for i := len(tests) - 1; i >= 0; i-- {
|
for i := len(tests) - 1; i >= 0; i-- {
|
||||||
if tests[i].Name == name {
|
if tests[i].Name == name {
|
||||||
|
7
testdata/22-bench.txt
vendored
Normal file
7
testdata/22-bench.txt
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: code.internal/state
|
||||||
|
BenchmarkParse-8 2000000 604 ns/op
|
||||||
|
BenchmarkReadingList-8 1000000 1425 ns/op
|
||||||
|
PASS
|
||||||
|
ok package/basic 3.212s
|
10
testdata/22-report.xml
vendored
Normal file
10
testdata/22-report.xml
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite tests="2" failures="0" time="3.212" name="package/basic">
|
||||||
|
<properties>
|
||||||
|
<property name="go.version" value="1.0"></property>
|
||||||
|
</properties>
|
||||||
|
<testcase classname="basic" name="BenchmarkParse" time="0.000000604"></testcase>
|
||||||
|
<testcase classname="basic" name="BenchmarkReadingList" time="0.000001425"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
7
testdata/23-benchmem.txt
vendored
Normal file
7
testdata/23-benchmem.txt
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: code.internal/state
|
||||||
|
BenchmarkIpsHistoryInsert-8 30000 52568 ns/op 24879 B/op 494 allocs/op
|
||||||
|
BenchmarkIpsHistoryLookup-8 100000 15208 ns/op 7369 B/op 143 allocs/op
|
||||||
|
PASS
|
||||||
|
ok package/one 9.415s
|
10
testdata/23-report.xml
vendored
Normal file
10
testdata/23-report.xml
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite tests="2" failures="0" time="9.415" name="package/one">
|
||||||
|
<properties>
|
||||||
|
<property name="go.version" value="1.0"></property>
|
||||||
|
</properties>
|
||||||
|
<testcase classname="one" name="BenchmarkIpsHistoryInsert" time="0.000052568" bytes="24879" allocs="494"></testcase>
|
||||||
|
<testcase classname="one" name="BenchmarkIpsHistoryLookup" time="0.000015208" bytes="7369" allocs="143"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
15
testdata/24-benchtests.txt
vendored
Normal file
15
testdata/24-benchtests.txt
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
=== RUN TestNew
|
||||||
|
=== RUN TestNew/no
|
||||||
|
=== RUN TestNew/normal
|
||||||
|
--- PASS: TestNew (0.00s)
|
||||||
|
--- PASS: TestNew/no (0.00s)
|
||||||
|
--- PASS: TestNew/normal (0.00s)
|
||||||
|
=== RUN TestWriteThis
|
||||||
|
--- PASS: TestWriteThis (0.00s)
|
||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: package3/baz
|
||||||
|
BenchmarkDeepMerge-8 500000 2611 ns/op 1110 B/op 16 allocs/op
|
||||||
|
BenchmarkNext-8 500000 100 ns/op 100 B/op 1 allocs/op
|
||||||
|
PASS
|
||||||
|
ok package3/baz 1.382s
|
14
testdata/24-report.xml
vendored
Normal file
14
testdata/24-report.xml
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite tests="6" failures="0" time="1.382" name="package3/baz">
|
||||||
|
<properties>
|
||||||
|
<property name="go.version" value="1.0"></property>
|
||||||
|
</properties>
|
||||||
|
<testcase classname="baz" name="TestNew" time="0.000"></testcase>
|
||||||
|
<testcase classname="baz" name="TestNew/no" time="0.000"></testcase>
|
||||||
|
<testcase classname="baz" name="TestNew/normal" time="0.000"></testcase>
|
||||||
|
<testcase classname="baz" name="TestWriteThis" time="0.000"></testcase>
|
||||||
|
<testcase classname="baz" name="BenchmarkDeepMerge" time="0.000002611" bytes="1110" allocs="16"></testcase>
|
||||||
|
<testcase classname="baz" name="BenchmarkNext" time="0.000000100" bytes="100" allocs="1"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
12
testdata/25-benchcount.txt
vendored
Normal file
12
testdata/25-benchcount.txt
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
BenchmarkNew-8 5000000 350 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkNew-8 5000000 357 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkNew-8 5000000 354 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkNew-8 5000000 358 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkNew-8 5000000 345 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 100 ns/op 20 B/op 1 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 105 ns/op 20 B/op 1 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 102 ns/op 20 B/op 1 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 102 ns/op 20 B/op 1 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 102 ns/op 20 B/op 1 allocs/op
|
||||||
|
PASS
|
||||||
|
ok pkg/count 14.211s
|
10
testdata/25-report.xml
vendored
Normal file
10
testdata/25-report.xml
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite tests="2" failures="0" time="14.211" name="pkg/count">
|
||||||
|
<properties>
|
||||||
|
<property name="go.version" value="1.0"></property>
|
||||||
|
</properties>
|
||||||
|
<testcase classname="count" name="BenchmarkNew" time="0.000000352" bytes="80" allocs="3"></testcase>
|
||||||
|
<testcase classname="count" name="BenchmarkFew" time="0.000000102" bytes="20" allocs="1"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
15
testdata/26-report.xml
vendored
Normal file
15
testdata/26-report.xml
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite tests="7" failures="0" time="14.211" name="multiple/repeating">
|
||||||
|
<properties>
|
||||||
|
<property name="go.version" value="1.0"></property>
|
||||||
|
</properties>
|
||||||
|
<testcase classname="repeating" name="TestRepeat" time="0.000"></testcase>
|
||||||
|
<testcase classname="repeating" name="TestRepeat" time="0.000"></testcase>
|
||||||
|
<testcase classname="repeating" name="TestRepeat" time="0.000"></testcase>
|
||||||
|
<testcase classname="repeating" name="TestRepeat" time="0.000"></testcase>
|
||||||
|
<testcase classname="repeating" name="TestRepeat" time="0.000"></testcase>
|
||||||
|
<testcase classname="repeating" name="BenchmarkNew" time="0.000000352" bytes="80" allocs="3"></testcase>
|
||||||
|
<testcase classname="repeating" name="BenchmarkFew" time="0.000000102" bytes="20" allocs="1"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
23
testdata/26-testbenchmultiple.txt
vendored
Normal file
23
testdata/26-testbenchmultiple.txt
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
=== RUN TestRepeat
|
||||||
|
--- PASS: TestRepeat (0.00s)
|
||||||
|
=== RUN TestRepeat
|
||||||
|
--- PASS: TestRepeat (0.00s)
|
||||||
|
=== RUN TestRepeat
|
||||||
|
--- PASS: TestRepeat (0.00s)
|
||||||
|
=== RUN TestRepeat
|
||||||
|
--- PASS: TestRepeat (0.00s)
|
||||||
|
=== RUN TestRepeat
|
||||||
|
--- PASS: TestRepeat (0.00s)
|
||||||
|
pkg: multiple/repeating
|
||||||
|
BenchmarkNew-8 5000000 350 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkNew-8 5000000 357 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkNew-8 5000000 354 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkNew-8 5000000 358 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkNew-8 5000000 345 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 100 ns/op 20 B/op 1 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 105 ns/op 20 B/op 1 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 102 ns/op 20 B/op 1 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 102 ns/op 20 B/op 1 allocs/op
|
||||||
|
BenchmarkFew-8 5000000 102 ns/op 20 B/op 1 allocs/op
|
||||||
|
PASS
|
||||||
|
ok multiple/repeating 14.211s
|
8
testdata/27-benchdecimal.txt
vendored
Normal file
8
testdata/27-benchdecimal.txt
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: really/small
|
||||||
|
BenchmarkItsy-8 30000000 45.7 ns/op
|
||||||
|
BenchmarkTeeny-8 1000000000 2.12 ns/op
|
||||||
|
BenchmarkWeeny-8 2000000000 0.26 ns/op
|
||||||
|
PASS
|
||||||
|
ok really/small 4.344s
|
11
testdata/27-report.xml
vendored
Normal file
11
testdata/27-report.xml
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite tests="3" failures="0" time="4.344" name="really/small">
|
||||||
|
<properties>
|
||||||
|
<property name="go.version" value="1.0"></property>
|
||||||
|
</properties>
|
||||||
|
<testcase classname="small" name="BenchmarkItsy" time="0.000000045"></testcase>
|
||||||
|
<testcase classname="small" name="BenchmarkTeeny" time="0.000000002"></testcase>
|
||||||
|
<testcase classname="small" name="BenchmarkWeeny" time="0.000000000"></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
Loading…
x
Reference in New Issue
Block a user