Atlas › Test

TestGenerateSuiteReports

Exact test identity: go.temporal.io/server/tools/flakereport/TestGenerateSuiteReports

Package
go.temporal.io/server/tools/flakereport
Suite / test hierarchy
TestGenerateSuiteReports
Test
TestGenerateSuiteReports
Introduced at
parser.go ×11 Frontier kind: Joint frontier
Covered ranges
13
Covered lines
58
Covered files
1

Covered source

Expand a file to inspect source; the > gutter marks covered lines.

go.temporal.io/server/tools/flakereport/parser.go 58 covered LOC · 13 ranges

Open complete file

60 // (starts with "Test" and contains "Suite").
61 // e.g. TestDeploymentVersionSuiteV0, TestFunctionalSuite
62 > func isGoTestSuite(name string) bool { parser.go
63 > return strings.HasPrefix(name, "Test") && strings.Contains(name, "Suite")
64 > }
65
66 // extractFailures extracts all test failures from parsed JUnit data
119 // normalizeTestName strips all trailing parenthesized suffixes from test names,
120 // e.g. "(retry 1)", "(final)", "(timeout)".
121 > func normalizeTestName(name string) string { parser.go
122 > for {
123 > stripped := trailingSuffixRegex.ReplaceAllString(name, "")
124 > if stripped == name {
125 > return name
126 > }
127 > name = stripped parser.go
128 }
129 }
418 // MatrixNames (DB configs). Keying by (RunID, MatrixName) ensures shards belonging to the
419 // same run+config are counted once, regardless of how many shard JobIDs they produce.
420 > func suiteRunKey(runID int64, matrixName string) string { parser.go
421 > return fmt.Sprintf("%d:%s", runID, matrixName)
422 > }
423
424 // generateSuiteReports creates per-suite flake breakdown from all failures and test runs.
425 // Suite flake rate = % of (CI run × DB config) pairs where the suite had at least one
426 // non-retry failure.
427 > func generateSuiteReports(allFailures []TestFailure, allTestRuns []TestRun) []SuiteReport { parser.go
428 > // Track unique (CI run × DB config) pairs per suite (denominator).
429 > // Using MatrixName avoids the inflation caused by per-shard JobIDs: suites whose
430 > // test methods are spread across N shards would otherwise be counted N times per
431 > // (run × DB config).
432 > suiteRuns := make(map[string]map[string]bool)
433 > for _, run := range allTestRuns {
434 > if run.Skipped || !isGoTestSuite(run.SuiteName) {
435 > continue
436 }
437 > if suiteRuns[run.SuiteName] == nil { parser.go
438 > suiteRuns[run.SuiteName] = make(map[string]bool)
439 > }
440 > suiteRuns[run.SuiteName][suiteRunKey(run.RunID, run.MatrixName)] = true
441 }
442
443 // Track (CI run × DB config) pairs with non-retry failures per suite (numerator)
444 > suiteFailedRuns := make(map[string]map[string]bool) parser.go
445 > suiteLastFailure := make(map[string]time.Time)
446 > for _, failure := range allFailures {
447 > if !isGoTestSuite(failure.SuiteName) {
448 continue
449 }
450 // Only report the original, complete run
451 > if normalizeTestName(failure.Name) != failure.Name { parser.go
452 > continue
453 }
454 > if suiteFailedRuns[failure.SuiteName] == nil { parser.go
455 > suiteFailedRuns[failure.SuiteName] = make(map[string]bool)
456 > }
457 > runKey := suiteRunKey(failure.RunID, failure.MatrixName)
458 > suiteFailedRuns[failure.SuiteName][runKey] = true
459 > if failure.Timestamp.After(suiteLastFailure[failure.SuiteName]) {
460 > suiteLastFailure[failure.SuiteName] = failure.Timestamp
461 > }
462 }
463
464 > var reports []SuiteReport parser.go
465 > for suiteName, runIDs := range suiteRuns {
466 > failedRuns := len(suiteFailedRuns[suiteName])
467 > if failedRuns == 0 {
468 > continue
469 }
470 > totalRuns := len(runIDs) parser.go
471 > flakeRate := float64(failedRuns) / float64(totalRuns) * 100.0
472 > reports = append(reports, SuiteReport{
473 > SuiteName: suiteName,
474 > FlakeRate: flakeRate,
475 > FailedRuns: failedRuns,
476 > TotalRuns: totalRuns,
477 > LastFailure: suiteLastFailure[suiteName],
478 > })
479 }
480
481 > sort.Slice(reports, func(i, j int) bool { parser.go
482 > return reports[i].SuiteName < reports[j].SuiteName
483 > })
484
485 > return reports parser.go
486 }