Skip to content

Commit 8e28a77

Browse files
committed
Separates panic tests
1 parent 92bda89 commit 8e28a77

File tree

6 files changed

+147
-38
lines changed

6 files changed

+147
-38
lines changed

tools/flakeguard/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
tmp_test_flaky_state
2-
flaky_test_results.json
2+
flaky_test_results_*.json

tools/flakeguard/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ test_unit:
66
test:
77
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
88
set -euo pipefail
9-
go list ./... | grep -v 'flaky_test_package' | xargs go test -json -cover -coverprofile unit-test-coverage.out -v 2>&1 | tee /tmp/gotest.log | gotestfmt
9+
go list ./... | grep -v 'flaky_test_package' | xargs go test -json -cover -coverprofile unit-test-coverage.out -v 2>&1 | tee /tmp/gotest.log | gotestfmt

tools/flakeguard/git/git_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
)
99

1010
func TestGetChangedGoPackagesFromDiff(t *testing.T) {
11+
t.Parallel()
12+
1113
tests := []struct {
1214
name string
1315
out string

tools/flakeguard/runner/flaky_test_package/flaky_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func TestSkipped(t *testing.T) {
4545
t.Skip("This test is intentionally skipped")
4646
}
4747

48-
// func TestPanic(t *testing.T) {
49-
// t.Parallel()
50-
// panic("This test intentionally panics")
51-
// }
48+
func TestPanic(t *testing.T) {
49+
t.Parallel()
50+
panic("This test intentionally panics")
51+
}

tools/flakeguard/runner/runner.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package runner
22

33
import (
44
"bufio"
5+
"bytes"
56
"encoding/json"
67
"errors"
78
"fmt"
9+
"io"
810
"log"
911
"os"
1012
"os/exec"
@@ -26,6 +28,8 @@ type Runner struct {
2628
FailFast bool // Stop on first test failure.
2729
SkipTests []string // Test names to exclude.
2830
SelectedTestPackages []string // Explicitly selected packages to run.
31+
CollectRawOutput bool // Collect test output for later inspection.
32+
rawOutput bytes.Buffer
2933
}
3034

3135
// RunTests executes the tests for each provided package and aggregates all results.
@@ -48,6 +52,11 @@ func (r *Runner) RunTests() ([]reports.TestResult, error) {
4852
return parseTestResults(jsonFilePaths)
4953
}
5054

55+
// RawOutput retrieves the raw output from the test runs, if CollectRawOutput enabled.
56+
func (r *Runner) RawOutput() bytes.Buffer {
57+
return r.rawOutput
58+
}
59+
5160
type exitCoder interface {
5261
ExitCode() int
5362
}
@@ -77,6 +86,13 @@ func (r *Runner) runTests(packageName string) (string, bool, error) {
7786
// Run the command with output directed to the file
7887
cmd := exec.Command("go", args...)
7988
cmd.Dir = r.ProjectPath
89+
if r.CollectRawOutput {
90+
cmd.Stdout = io.MultiWriter(tmpFile, &r.rawOutput)
91+
cmd.Stderr = io.MultiWriter(tmpFile, &r.rawOutput)
92+
} else {
93+
cmd.Stdout = tmpFile
94+
cmd.Stderr = tmpFile
95+
}
8096
cmd.Stdout = tmpFile
8197
cmd.Stderr = tmpFile
8298

@@ -157,7 +173,7 @@ func parseTestResults(filePaths []string) ([]reports.TestResult, error) {
157173
if entry.Output != "" {
158174
if entry.Test != "" {
159175
// Test-level output
160-
result.Outputs = append(result.Outputs, entry.Output)
176+
result.Outputs = append(result.Outputs, strings.TrimSpace(entry.Output))
161177
} else {
162178
// Package-level output
163179
// Append to PackageOutputs of all TestResults in the same package

tools/flakeguard/runner/runner_test.go

Lines changed: 122 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,27 @@ func (m MockGoRunner) RunCommand(dir string, args []string) (string, bool, error
1919
return m.RunFunc(dir, args)
2020
}
2121

22-
func TestRun(t *testing.T) {
23-
t.Parallel()
24-
25-
runs := 5
22+
type expectedTestResult struct {
23+
TestResult *reports.TestResult
24+
seen bool
25+
}
2626

27-
runner := Runner{
27+
var (
28+
defaultRuns = 5
29+
defaultTestRunner = Runner{
2830
ProjectPath: "./",
2931
Verbose: true,
30-
RunCount: runs,
32+
RunCount: defaultRuns,
3133
UseRace: false,
32-
SkipTests: []string{},
34+
SkipTests: []string{"TestPanic"},
3335
FailFast: false,
3436
SelectedTestPackages: []string{"./flaky_test_package"},
37+
CollectRawOutput: true,
3538
}
39+
)
3640

37-
expectedResults := map[string]*struct {
38-
*reports.TestResult
39-
seen bool
40-
}{
41+
func TestRunDefault(t *testing.T) {
42+
expectedResults := map[string]*expectedTestResult{
4143
"TestFlaky": {
4244
TestResult: &reports.TestResult{
4345
TestName: "TestFlaky",
@@ -51,7 +53,7 @@ func TestRun(t *testing.T) {
5153
Panicked: false,
5254
Skipped: false,
5355
PassRatio: 0,
54-
Failures: runs,
56+
Failures: defaultRuns,
5557
},
5658
},
5759
"TestPass": {
@@ -60,17 +62,9 @@ func TestRun(t *testing.T) {
6062
Panicked: false,
6163
Skipped: false,
6264
PassRatio: 1,
63-
Successes: runs,
65+
Successes: defaultRuns,
6466
},
6567
},
66-
// "TestPanic": {
67-
// TestResult: &reports.TestResult{
68-
// TestName: "TestPanic",
69-
// Panicked: true,
70-
// Skipped: false,
71-
// PassRatio: 0,
72-
// },
73-
// },
7468
"TestSkipped": {
7569
TestResult: &reports.TestResult{
7670
TestName: "TestSkipped",
@@ -81,32 +75,129 @@ func TestRun(t *testing.T) {
8175
},
8276
}
8377

84-
testResults, err := runner.RunTests()
78+
testResults, err := defaultTestRunner.RunTests()
8579
require.NoError(t, err)
8680
t.Cleanup(func() {
8781
if t.Failed() {
88-
t.Log("Writing test results to flaky_test_results.json")
82+
resultsFileName := fmt.Sprintf("flaky_test_results_%s.json", t.Name())
83+
t.Logf("Writing test results to %s", resultsFileName)
8984
jsonResults, err := json.Marshal(testResults)
9085
require.NoError(t, err)
91-
err = os.WriteFile("flaky_test_results.json", jsonResults, 0644) //nolint:gosec
86+
err = os.WriteFile(resultsFileName, jsonResults, 0644) //nolint:gosec
9287
require.NoError(t, err)
9388
}
9489
})
90+
9591
for _, result := range testResults {
9692
t.Run(fmt.Sprintf("checking results of %s", result.TestName), func(t *testing.T) {
9793
expected, ok := expectedResults[result.TestName]
98-
// Sanity checks
9994
require.True(t, ok, "unexpected test result: %s", result.TestName)
10095
require.False(t, expected.seen, "test '%s' was seen multiple times", result.TestName)
10196
expected.seen = true
10297

103-
assert.Equal(t, runs, result.Runs, "test '%s' had an unexpected number of runs", result.TestName)
104-
assert.Len(t, result.Durations, runs, "test '%s' had an unexpected number of durations as it was run %d times", result.TestName, runs)
105-
if result.TestName == "TestSlow" {
106-
for _, duration := range result.Durations {
107-
assert.GreaterOrEqual(t, duration, float64(1), "slow test '%s' should have a duration of at least 2s", result.TestName)
108-
}
98+
assert.Equal(t, defaultRuns, result.Runs, "test '%s' had an unexpected number of runs", result.TestName)
99+
assert.Len(t, result.Durations, result.Runs, "test '%s' has a mismatch of runs and duration counts", result.TestName, defaultRuns)
100+
resultCounts := result.Successes + result.Failures + result.Panics + result.Skips
101+
assert.Equal(t, result.Runs, resultCounts,
102+
"test '%s' doesn't match Runs count with results counts\nRuns: %d\nSuccesses: %d\nFailures: %d\nPanics: %d\nSkips: %d\nTotal: %d",
103+
result.TestName, result.Runs, result.Successes, result.Failures, result.Panics, result.Skips, resultCounts,
104+
)
105+
assert.Equal(t, expected.TestResult.Panicked, result.Panicked, "test '%s' had an unexpected panic result", result.TestName)
106+
assert.Equal(t, expected.TestResult.Skipped, result.Skipped, "test '%s' had an unexpected skipped result", result.TestName)
107+
108+
if result.TestName == "TestFlaky" {
109+
assert.Greater(t, result.Successes, 0, "flaky test '%s' should have passed some", result.TestName)
110+
assert.Greater(t, result.Failures, 0, "flaky test '%s' should have failed some", result.TestName)
111+
assert.Greater(t, result.PassRatio, float64(0), "flaky test '%s' should have a flaky pass ratio", result.TestName)
112+
assert.Less(t, result.PassRatio, float64(1), "flaky test '%s' should have a flaky pass ratio", result.TestName)
113+
} else {
114+
assert.Equal(t, expected.TestResult.PassRatio, result.PassRatio, "test '%s' had an unexpected pass ratio", result.TestName)
115+
assert.Equal(t, expected.TestResult.Successes, result.Successes, "test '%s' had an unexpected number of successes", result.TestName)
116+
assert.Equal(t, expected.TestResult.Failures, result.Failures, "test '%s' had an unexpected number of failures", result.TestName)
109117
}
118+
})
119+
}
120+
121+
for _, expected := range expectedResults {
122+
assert.True(t, expected.seen, "expected test '%s' not found in test runs", expected.TestResult.TestName)
123+
}
124+
}
125+
126+
func TestRunWithPanics(t *testing.T) {
127+
panicRunner := defaultTestRunner
128+
panicRunner.SkipTests = []string{}
129+
130+
expectedResults := map[string]*expectedTestResult{
131+
"TestFlaky": {
132+
TestResult: &reports.TestResult{
133+
TestName: "TestFlaky",
134+
Panicked: true,
135+
Skipped: false,
136+
},
137+
},
138+
"TestFail": {
139+
TestResult: &reports.TestResult{
140+
TestName: "TestFail",
141+
Panicked: false,
142+
Skipped: false,
143+
PassRatio: 0,
144+
Failures: defaultRuns,
145+
},
146+
},
147+
"TestPass": {
148+
TestResult: &reports.TestResult{
149+
TestName: "TestPass",
150+
Panicked: true,
151+
Skipped: false,
152+
PassRatio: 1,
153+
Successes: defaultRuns,
154+
},
155+
},
156+
"TestSkipped": {
157+
TestResult: &reports.TestResult{
158+
TestName: "TestSkipped",
159+
Panicked: true,
160+
Skipped: true,
161+
PassRatio: 0,
162+
},
163+
},
164+
"TestPanic": {
165+
TestResult: &reports.TestResult{
166+
TestName: "TestPanic",
167+
Panicked: true,
168+
Skipped: false,
169+
},
170+
},
171+
}
172+
173+
testResults, err := panicRunner.RunTests()
174+
require.NoError(t, err)
175+
t.Cleanup(func() {
176+
if t.Failed() {
177+
resultsFileName := fmt.Sprintf("flaky_test_results_%s.json", t.Name())
178+
t.Logf("Writing test results to %s", resultsFileName)
179+
jsonResults, err := json.Marshal(testResults)
180+
require.NoError(t, err)
181+
err = os.WriteFile(resultsFileName, jsonResults, 0644) //nolint:gosec
182+
require.NoError(t, err)
183+
}
184+
})
185+
186+
for _, result := range testResults {
187+
t.Run(fmt.Sprintf("checking results of %s", result.TestName), func(t *testing.T) {
188+
expected, ok := expectedResults[result.TestName]
189+
// Sanity checks
190+
require.True(t, ok, "unexpected test result: %s", result.TestName)
191+
require.False(t, expected.seen, "test '%s' was seen multiple times", result.TestName)
192+
expected.seen = true
193+
194+
assert.Equal(t, defaultRuns, result.Runs, "test '%s' had an unexpected number of runs", result.TestName)
195+
assert.Len(t, result.Durations, result.Runs, "test '%s' has a mismatch of runs and duration counts", result.TestName, defaultRuns)
196+
resultCounts := result.Successes + result.Failures + result.Panics + result.Skips
197+
assert.Equal(t, result.Runs, resultCounts,
198+
"test '%s' doesn't match Runs count with results counts\nRuns: %d\nSuccesses: %d\nFailures: %d\nPanics: %d\nSkips: %d\nTotal: %d",
199+
result.TestName, result.Runs, result.Successes, result.Failures, result.Panics, result.Skips, resultCounts,
200+
)
110201
assert.Equal(t, expected.TestResult.Panicked, result.Panicked, "test '%s' had an unexpected panic result", result.TestName)
111202
assert.Equal(t, expected.TestResult.Skipped, result.Skipped, "test '%s' had an unexpected skipped result", result.TestName)
112203

0 commit comments

Comments
 (0)