Skip to content

Commit 990bf47

Browse files
committed
Slimmer reporting
1 parent 20407f2 commit 990bf47

File tree

6 files changed

+74
-53
lines changed

6 files changed

+74
-53
lines changed

tools/flakeguard/.gitignore

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
tmp_test_flaky_state
1+
tmp_test_flaky*
22
test_results_*.json
33
debug_outputs/
4-
example_results.json
5-
example_results.md
4+
example_results/
5+
example*.json
6+
example*.md

tools/flakeguard/Makefile

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,18 @@ test:
1010

1111
.PHONY: example
1212
example:
13-
go run . run --project-path=./runner --test-packages=./example_test_package --run-count=5 --skip-tests=TestPanic --max-pass-ratio=1 --race=false --output-json=example_results.json
13+
rm -rf example_results
14+
mkdir -p example_results
15+
- go run . run --project-path=./runner --test-packages=./example_test_package --run-count=5 --skip-tests=TestPanic,TestFlakyPanic --max-pass-ratio=1 --race=false --output-json=example_results/example_run_1.json
16+
- go run . run --project-path=./runner --test-packages=./example_test_package --run-count=5 --skip-tests=TestPanic,TestFlakyPanic --max-pass-ratio=1 --race=false --output-json=example_results/example_run_2.json
17+
- go run . run --project-path=./runner --test-packages=./example_test_package --run-count=5 --skip-tests=TestPanic,TestFlakyPanic --max-pass-ratio=1 --race=false --output-json=example_results/example_run_3.json
18+
go run . aggregate-results --results-path ./example_results --output-results ./example_results/all_tests_example.json
19+
20+
.PHONY: example_panic
21+
example_panic:
22+
rm -rf example_results
23+
mkdir -p example_results
24+
- go run . run --project-path=./runner --test-packages=./example_test_package --run-count=5 --skip-tests=TestPanic --max-pass-ratio=1 --race=false --output-json=example_results/example_run_1.json
25+
- go run . run --project-path=./runner --test-packages=./example_test_package --run-count=5 --skip-tests=TestPanic --max-pass-ratio=1 --race=false --output-json=example_results/example_run_2.json
26+
- go run . run --project-path=./runner --test-packages=./example_test_package --run-count=5 --skip-tests=TestPanic --max-pass-ratio=1 --race=false --output-json=example_results/example_run_3.json
27+
go run . aggregate-results --results-path ./example_results --output-results ./example_results/all_tests_example.json

tools/flakeguard/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,13 @@ Run with `--help` to see all flags for the commands.
3030
### JSON Output
3131

3232
Both `find` and `run` commands support JSON output `--json`, making it easy to integrate Flakeguard with CI/CD pipelines and reporting tools.
33+
34+
### Example Run
35+
36+
You can find example usage and see outputs with:
37+
38+
```sh
39+
make example # Run an example flow of running tests and aggregating results
40+
make example_panic # Run example flow with panicking tests
41+
ls example_results # See results of each run and aggregation
42+
```

tools/flakeguard/reports/reports.go

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func AggregateTestResults(folderPath string) (*TestReport, error) {
119119
for _, test := range report.ExcludedTests {
120120
excludedTests[test] = struct{}{}
121121
}
122-
// Process each test result
122+
// Process each test results
123123
for _, result := range report.Results {
124124
// Unique key for each test based on TestName and TestPackage
125125
key := result.TestName + "|" + result.TestPackage
@@ -180,7 +180,7 @@ func AggregateTestResults(folderPath string) (*TestReport, error) {
180180
// PrintTests prints tests in a pretty format
181181
func PrintTests(w io.Writer, tests []TestResult, maxPassRatio float64) (allRuns, passes, fails, panics, skips, races, flakes int) {
182182
headers := []string{
183-
"Test Name", "Test Package", "Pass Ratio", "Skipped", "Runs", "Successes", "Failures", "Panics", "Races", "Skips", "Avg Duration",
183+
"**Test Name**", "**Test Package**", "**Package Panicked**", "**Pass Ratio**", "**Runs**", "**Successes**", "**Failures**", "**Panics**", "**Races**", "**Skips**", "**Avg Duration**",
184184
}
185185

186186
// Build test rows and summary data
@@ -190,8 +190,8 @@ func PrintTests(w io.Writer, tests []TestResult, maxPassRatio float64) (allRuns,
190190
rows = append(rows, []string{
191191
test.TestName,
192192
test.TestPackage,
193+
fmt.Sprintf("%t", test.PackagePanicked),
193194
fmt.Sprintf("%.2f%%", test.PassRatio*100),
194-
fmt.Sprintf("%v", test.Skipped),
195195
fmt.Sprintf("%d", test.Runs),
196196
fmt.Sprintf("%d", test.Successes),
197197
fmt.Sprintf("%d", test.Failures),
@@ -208,19 +208,21 @@ func PrintTests(w io.Writer, tests []TestResult, maxPassRatio float64) (allRuns,
208208
skips += test.Skips
209209
races += test.Races
210210
panics += test.Panics
211-
flakes += fails + races + panics
211+
if test.PassRatio < maxPassRatio {
212+
flakes++
213+
}
212214
}
213215

214216
// Print out summary data
215217
summaryData := [][]string{
216-
{"**Summary**", "**Value**"},
217-
{"Runs", fmt.Sprint(allRuns)},
218-
{"Passes", fmt.Sprint(passes)},
219-
{"Failures", fmt.Sprint(fails)},
220-
{"Panics", fmt.Sprint(panics)},
221-
{"Skips", fmt.Sprint(skips)},
222-
{"Races", fmt.Sprint(races)},
223-
{"Flakes", fmt.Sprint(flakes)},
218+
{"**Category**", "**Total**"},
219+
{"**Runs**", fmt.Sprint(allRuns)},
220+
{"**Passes**", fmt.Sprint(passes)},
221+
{"**Failures**", fmt.Sprint(fails)},
222+
{"**Panics**", fmt.Sprint(panics)},
223+
{"**Skips**", fmt.Sprint(skips)},
224+
{"**Races**", fmt.Sprint(races)},
225+
{"**Flaky Tests**", fmt.Sprint(flakes)},
224226
}
225227
colWidths := make([]int, len(rows[0]))
226228

@@ -238,13 +240,11 @@ func PrintTests(w io.Writer, tests []TestResult, maxPassRatio float64) (allRuns,
238240
printSeparator := func() {
239241
fmt.Fprintf(w, "|-%s-|-%s-|\n", strings.Repeat("-", colWidths[0]), strings.Repeat("-", colWidths[1]))
240242
}
241-
printSeparator()
242243
printRow(summaryData[0])
243244
printSeparator()
244245
for _, row := range summaryData[1:] {
245246
printRow(row)
246247
}
247-
printSeparator()
248248
fmt.Fprintln(w)
249249

250250
// Print out test data
@@ -277,17 +277,11 @@ func PrintTests(w io.Writer, tests []TestResult, maxPassRatio float64) (allRuns,
277277
}
278278

279279
// Print table
280-
printSeparator()
281280
printRow(headers)
282281
printSeparator()
283282
for _, row := range rows {
284283
printRow(row)
285284
}
286-
printSeparator()
287-
288-
// Print totals
289-
fmt.Fprintf(w, "\nSummary:\n")
290-
fmt.Fprintf(w, "Total Runs: %d, Passes: %d, Failures: %d, Panics: %d, Races: %d, Skips: %d\n", allRuns, passes, fails, panics, races, skips)
291285
return
292286
}
293287

@@ -326,13 +320,11 @@ func MarkdownSummary(w io.Writer, testReport *TestReport, maxPassRatio float64)
326320
}
327321
fmt.Fprint(w, "# Flakeguard Summary\n\n")
328322
// Print settings data
329-
printSeparator()
330323
printRow(rows[0])
331324
printSeparator()
332325
for _, row := range rows[1:] {
333326
printRow(row)
334327
}
335-
printSeparator()
336328
fmt.Fprintln(w)
337329

338330
if len(tests) == 0 {
@@ -345,11 +337,11 @@ func MarkdownSummary(w io.Writer, testReport *TestReport, maxPassRatio float64)
345337
avgPassRatio = float64(passes) / float64(allRuns)
346338
}
347339
if avgPassRatio < maxPassRatio {
348-
fmt.Fprintln(w, "## Found Flaky Tests :x:")
340+
fmt.Fprint(w, "## Found Flaky Tests :x:\n\n")
349341
} else {
350-
fmt.Fprintln(w, "## No Flakes Found :white_check_mark:")
342+
fmt.Fprint(w, "## No Flakes Found :white_check_mark:\n\n")
351343
}
352-
fmt.Fprintf(w, "Ran `%d` tests `%d` times with a `%.2f%%` pass ratio and found `%d` flaky tests\n\n", len(tests), allRuns, avgPassRatio*100, flakes)
344+
fmt.Fprintf(w, "Ran `%d` tests `%d` times, and found `%d` flaky tests with an overall `%.2f%%` pass ratio\n\n", len(tests), testReport.TestRunCount, flakes, avgPassRatio*100)
353345
if avgPassRatio < maxPassRatio {
354346
fmt.Fprint(w, "### Flakes\n\n")
355347
fmt.Fprint(w, testsData.String())

tools/flakeguard/runner/example_test_package/example_tests_test.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,26 +51,26 @@ func TestPanic(t *testing.T) {
5151
panic("This test intentionally panics")
5252
}
5353

54-
// func TestFlakyPanic(t *testing.T) {
55-
// t.Parallel()
56-
57-
// // Track if the test has run before
58-
// stateFile := "tmp_test_flaky_panic_state"
59-
60-
// // If the state file does not exist, create it and fail the test
61-
// if _, err := os.Stat(stateFile); os.IsNotExist(err) {
62-
// if err := os.WriteFile(stateFile, []byte("run once"), 0644); err != nil { //nolint:gosec
63-
// t.Fatalf("THIS IS UNEXPECTED: failed to create state file: %v", err)
64-
// }
65-
// panic("This is a designed flaky test panicking as intended")
66-
// }
67-
// t.Cleanup(func() {
68-
// err := os.Remove(stateFile)
69-
// if err != nil {
70-
// t.Fatalf("THIS IS UNEXPECTED: failed to remove state file: %v", err)
71-
// }
72-
// })
73-
// }
54+
func TestFlakyPanic(t *testing.T) {
55+
t.Parallel()
56+
57+
// Track if the test has run before
58+
stateFile := "tmp_test_flaky_panic_state"
59+
60+
// If the state file does not exist, create it and fail the test
61+
if _, err := os.Stat(stateFile); os.IsNotExist(err) {
62+
if err := os.WriteFile(stateFile, []byte("run once"), 0644); err != nil { //nolint:gosec
63+
t.Fatalf("THIS IS UNEXPECTED: failed to create state file: %v", err)
64+
}
65+
panic("This is a designed flaky test panicking as intended")
66+
}
67+
t.Cleanup(func() {
68+
err := os.Remove(stateFile)
69+
if err != nil {
70+
t.Fatalf("THIS IS UNEXPECTED: failed to remove state file: %v", err)
71+
}
72+
})
73+
}
7474

7575
func TestRace(t *testing.T) {
7676
t.Parallel()

tools/flakeguard/runner/runner.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,14 @@ func (r *Runner) RunTests() (*reports.TestReport, error) {
7070
return nil, fmt.Errorf("failed to parse test results: %w", err)
7171
}
7272
for index, report := range results {
73-
if report.Panics >= r.RunCount { // This feels hacky, but there aren't any elegant solutions
74-
results[index].Failures = 0 // We can sometimes double-count panics as failures
75-
results[index].Panics = r.RunCount
76-
results[index].Runs = r.RunCount
73+
if report.Runs > r.RunCount { // Panics can introduce double-counting test runs and mask panics as failures, this is a bit of a hacky way around it
74+
if report.Panics > 0 {
75+
results[index].Failures = 0 // We can sometimes double-count panics as failures
76+
results[index].Panics = r.RunCount
77+
results[index].Runs = r.RunCount
78+
} else {
79+
log.Printf("WARN: %s is reporting it ran %d times but it should have only ran %d", report.TestName, report.Runs, r.RunCount)
80+
}
7781
}
7882
}
7983
return &reports.TestReport{

0 commit comments

Comments
 (0)