Skip to content

Commit

Permalink
Calculating the test suite duraion from timestamps (#4281)
Browse files Browse the repository at this point in the history
**What type of PR is this?**
Bug fix

**What does this PR do? Why is it needed?**
When test cases use `t.Parallel()`, the duration of a test suite is more
than that of the test case with the same name. For example, when we run
this test:

```go
func TestParallel(t *testing.T) {
	t.Run("Test 1", func(t *testing.T) {
		time.Sleep(1 * time.Second)
	})

	t.Run("Test 2", func(t *testing.T) {
		t.Parallel()
		time.Sleep(2 * time.Second)
	})
}
```

The log shows:

```
=== RUN   TestParallel
=== RUN   TestParallel/Test_1
=== RUN   TestParallel/Test_2
=== PAUSE TestParallel/Test_2
=== CONT  TestParallel/Test_2
--- PASS: TestParallel (1.00s)
    --- PASS: TestParallel/Test_1 (1.00s)
    --- PASS: TestParallel/Test_2 (2.00s)
PASS
```

`TestParallel/Test_2` took 2 seconds, but the test case `TestParallel`
only took 1 second. Apparently, the test suite `TestParallel` should
have taken more than 1 second.

This PR uses the timestamps from JSON events to determine end to end
time of a test suite.
  • Loading branch information
linzhp authored Feb 23, 2025
1 parent b1f9017 commit 3af0c6f
Showing 1 changed file with 18 additions and 6 deletions.
24 changes: 18 additions & 6 deletions go/tools/bzltestutil/xml.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ type testCase struct {
state string
output strings.Builder
duration *float64
timestamp *time.Time
start *time.Time
end *time.Time
}

const (
Expand Down Expand Up @@ -106,7 +107,7 @@ func json2xml(r io.Reader, pkgName string) ([]byte, error) {
case "run":
if c := testCaseByName(e.Test); c != nil {
c.state = s
c.timestamp = e.Time
c.start = e.Time
}
case "output":
trimmedOutput := strings.TrimSpace(e.Output)
Expand Down Expand Up @@ -137,22 +138,26 @@ func json2xml(r io.Reader, pkgName string) ([]byte, error) {
}
if c := testCaseByName(e.Test); c != nil {
c.output.WriteString(e.Output)
c.end = e.Time
}
case "skip":
if c := testCaseByName(e.Test); c != nil {
c.output.WriteString(e.Output)
c.state = s
c.duration = e.Elapsed
c.end = e.Time
}
case "fail":
if c := testCaseByName(e.Test); c != nil {
c.state = s
c.duration = e.Elapsed
c.end = e.Time
}
case "pass":
if c := testCaseByName(e.Test); c != nil {
c.duration = e.Elapsed
c.state = s
c.end = e.Time
}
}
}
Expand Down Expand Up @@ -183,11 +188,18 @@ func toXML(pkgName string, testcases map[string]*testCase) *xmlTestSuites {
}
c := testcases[name]
if name == suiteName {
if c.duration != nil {
suite.Time = fmt.Sprintf("%.3f", *c.duration)
duration := *c.duration
if c.start != nil && c.end != nil {
// the duration of a test suite may be greater than c.duration
// when any test case uses t.Parallel().
d := c.end.Sub(*c.start).Seconds()
if d > duration {
duration = d
}
}
if c.timestamp != nil {
suite.Timestamp = c.timestamp.Format("2006-01-02T15:04:05.000Z")
suite.Time = fmt.Sprintf("%.3f", duration)
if c.start != nil {
suite.Timestamp = c.start.Format("2006-01-02T15:04:05.000Z")
}
}
suite.Tests++
Expand Down

0 comments on commit 3af0c6f

Please sign in to comment.