mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Log per-test durations during integration tests
To spot slow or anomalous tests across CI runs, record each test's run duration when LAZYGIT_TEST_TIMING is set (to a file path); run_integration_tests.sh prints them at the end, sorted by slowest first. CI sets it for all integration jobs. The harness appends to a file rather than writing to stdout/stderr because `go test` captures those and only surfaces them with -v, which would drown the signal in every test's verbose logs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
03a914c04c
commit
b6b5436d57
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
|
@ -109,6 +109,9 @@ jobs:
|
|||
# by default on the Linux runner, but we set it explicitly to be safe.
|
||||
LAZYGIT_RACE_DETECTOR: ${{ matrix.race && '1' || '' }}
|
||||
CGO_ENABLED: ${{ matrix.race && '1' || '' }}
|
||||
# Append each test's duration to this file; run_integration_tests.sh
|
||||
# prints the slowest at the end, to spot slow/anomalous tests.
|
||||
LAZYGIT_TEST_TIMING: /tmp/test_timings.txt
|
||||
run: |
|
||||
mkdir -p /tmp/code_coverage
|
||||
./scripts/run_integration_tests.sh
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ func TestIntegration(t *testing.T) {
|
|||
parallelTotal := tryConvert(os.Getenv("PARALLEL_TOTAL"), 1)
|
||||
parallelIndex := tryConvert(os.Getenv("PARALLEL_INDEX"), 0)
|
||||
raceDetector := os.Getenv("LAZYGIT_RACE_DETECTOR") != ""
|
||||
logTimingsPath := os.Getenv("LAZYGIT_TEST_TIMING")
|
||||
// LAZYGIT_GOCOVERDIR is the directory where we write coverage files to. If this directory
|
||||
// is defined, go binaries built with the -cover flag will write coverage files to
|
||||
// to it.
|
||||
|
|
@ -58,7 +59,8 @@ func TestIntegration(t *testing.T) {
|
|||
CodeCoverageDir: codeCoverageDir,
|
||||
InputDelay: 0,
|
||||
// Allow two attempts at each test to get around flakiness
|
||||
MaxAttempts: 1,
|
||||
MaxAttempts: 1,
|
||||
LogTimingsPath: logTimingsPath,
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
lazycoreUtils "github.com/jesseduffield/lazycore/pkg/utils"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
|
|
@ -24,6 +26,12 @@ type RunTestArgs struct {
|
|||
CodeCoverageDir string
|
||||
InputDelay int
|
||||
MaxAttempts int
|
||||
// If set, each test's run duration is appended to this file (as
|
||||
// "<seconds> <test name>"). run_integration_tests.sh prints the slowest at
|
||||
// the end, so slow or anomalous tests can be spotted across CI runs. We
|
||||
// write to a file rather than stdout/stderr because `go test` captures
|
||||
// those and only shows them with -v. Empty disables it.
|
||||
LogTimingsPath string
|
||||
}
|
||||
|
||||
// This function lets you run tests either from within `go test` or from a regular binary.
|
||||
|
|
@ -47,6 +55,11 @@ func RunTests(args RunTestArgs) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Start each run with a fresh timings file (see RunTestArgs.LogTimingsPath).
|
||||
if args.LogTimingsPath != "" {
|
||||
_ = os.Remove(args.LogTimingsPath)
|
||||
}
|
||||
|
||||
for _, test := range args.Tests {
|
||||
args.TestWrapper(test, func() error {
|
||||
paths := NewPaths(
|
||||
|
|
@ -99,7 +112,11 @@ func runTest(
|
|||
return err
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
pid, err := args.RunCmd(cmd)
|
||||
if args.LogTimingsPath != "" {
|
||||
logTestTiming(args.LogTimingsPath, test.Name(), time.Since(start))
|
||||
}
|
||||
|
||||
// Print race detector log regardless of the command's exit status
|
||||
if args.RaceDetector {
|
||||
|
|
@ -112,6 +129,23 @@ func runTest(
|
|||
return err
|
||||
}
|
||||
|
||||
// timingsMutex serializes appends to the timings file, since tests run in
|
||||
// parallel.
|
||||
var timingsMutex sync.Mutex
|
||||
|
||||
func logTestTiming(path, name string, duration time.Duration) {
|
||||
timingsMutex.Lock()
|
||||
defer timingsMutex.Unlock()
|
||||
|
||||
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fmt.Fprintf(f, "%.2f %s\n", duration.Seconds(), name)
|
||||
}
|
||||
|
||||
func prepareTestDir(
|
||||
test *IntegrationTest,
|
||||
paths Paths,
|
||||
|
|
|
|||
|
|
@ -37,4 +37,12 @@ if test -f ~/.gitconfig.lazygit.bak; then
|
|||
mv ~/.gitconfig.lazygit.bak ~/.gitconfig
|
||||
fi
|
||||
|
||||
# If per-test timings were collected (LAZYGIT_TEST_TIMING points at the file the
|
||||
# harness appends to), print them sorted by slowest first so they show up in the
|
||||
# CI log.
|
||||
if [ -n "$LAZYGIT_TEST_TIMING" ] && [ -f "$LAZYGIT_TEST_TIMING" ]; then
|
||||
echo "Test timings (seconds):"
|
||||
sort -rn "$LAZYGIT_TEST_TIMING"
|
||||
fi
|
||||
|
||||
exit $EXITCODE
|
||||
|
|
|
|||
Loading…
Reference in a new issue