Skip to content

Commit

Permalink
go junitxml: compute per package start times rather than using per ex…
Browse files Browse the repository at this point in the history
…ecution

This can be pretty meaningful if people want to build a timeline of when
what test packages were executing. One example use case would be building
a trace view ala https://docs.datadoghq.com/tests/setup/junit_xml/?tab=linux.
  • Loading branch information
zdylag committed May 13, 2024
1 parent e9677fb commit 412760c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
14 changes: 13 additions & 1 deletion internal/junitxml/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,23 @@ func generate(exec *testjson.Execution, cfg Config) JUnitTestSuites {
if cfg.customElapsed != "" {
suites.Time = cfg.customElapsed
}

overallEarliestTimestamp, ok := exec.EarliestTime()
if !ok {
overallEarliestTimestamp = exec.Started()
}

for _, pkgname := range exec.Packages() {
pkg := exec.Package(pkgname)
if cfg.HideEmptyPackages && pkg.IsEmpty() {
continue
}

earliestTimestamp, ok := pkg.EarliestTime()
if !ok {
earliestTimestamp = overallEarliestTimestamp
}

junitpkg := JUnitTestSuite{
Name: cfg.FormatTestSuiteName(pkgname),
Tests: pkg.Total,
Expand All @@ -119,7 +131,7 @@ func generate(exec *testjson.Execution, cfg Config) JUnitTestSuites {
Timestamp: cfg.customTimestamp,
}
if cfg.customTimestamp == "" {
junitpkg.Timestamp = exec.Started().Format(time.RFC3339)
junitpkg.Timestamp = earliestTimestamp.Format(time.RFC3339)
}
suites.Suites = append(suites.Suites, junitpkg)
}
Expand Down
39 changes: 39 additions & 0 deletions testjson/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,23 @@ func (p *Package) TestCases() []TestCase {
return tc
}

// EarliestTime returns the earliest start time found within a child test case,
// and a bool for if any such time was found.
func (p *Package) EarliestTime() (time.Time, bool) {
found := false
t := time.Time{}

for _, tc := range p.TestCases() {
if !found || tc.Time.Before(t) {
t = tc.Time
}

found = true
}

return t, found
}

// LastFailedByName returns the most recent test with name in the list of Failed
// tests. If no TestCase is found with that name, an empty TestCase is returned.
//
Expand Down Expand Up @@ -652,6 +669,28 @@ func (e *Execution) Started() time.Time {
return e.started
}

// EarliestTime returns the earliest runtime found in any of the packages within this execution,
// and a bool to say whether or not a time was found.
func (e *Execution) EarliestTime() (time.Time, bool) {
found := false
t := time.Time{}

for _, p := range e.packages {
candidate, ok := p.EarliestTime()
if !ok {
continue
}

if !found || candidate.Before(t) {
t = candidate
}

found = true
}

return t, found
}

// newExecution returns a new Execution and records the current time as the
// time the test execution started.
func newExecution() *Execution {
Expand Down

0 comments on commit 412760c

Please sign in to comment.