Skip to content

test: a test gets 30 s before vitest calls it hung - #99

Merged
krzysztof-smartdataengines merged 1 commit into
mainfrom
test/vitest-hang-budget
Sep 27, 2026
Merged

krzysztof-smartdataengines merged 1 commit into
mainfrom
test/vitest-hang-budget

Conversation

@krzysztof-smartdataengines

@krzysztof-smartdataengines krzysztof-smartdataengines commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

A TypeScript test now gets 30 s before vitest reports it as hung. Before this it got vitest's
default of 5 s. On this workstation the 5 s budget reported four tests as failed that were not
hung. It changes one setting in typescript/vitest.config.ts and adds a paragraph to
docs/test-toolchain.md.

What was measured

On 27 September, four tests went over 5 s in make check runs for #93, #96 and #97. Another
session's build and tests held the load average at about 8 on four threads. The same tests on an
idle machine, from the JSON reporter:

Test Idle Loaded
weather.test.ts, an uncertain absent batch 401 ms over 5 s
frozen-verification.live.test.ts, the request captured before metadata calls 784 ms over 5 s
frozen-verification.live.test.ts, a target-only row 1114 ms over 5 s
generation-migration.live.test.ts, historical epochs from PostgreSQL 1724 ms over 5 s

Each was a slow test, not a hang. Each passed on a rerun of the same tree.

71 tests already carry a budget of their own, from 15 s to 120 s, and keep it. The count comes from
a throwaway reporter that read each test's timeout. The idle durations come from the JSON reporter.

Why a single number

The budget is a hang detector. A hung test never finishes, so the number only decides how long it
takes to say so, and 30 s stays finite. 928 tests use the default budget, and the slowest of them
takes 1.9 s on an idle machine. Today's worst slowdown was at least fourteenfold, on the first
runWeather call of weather.test.ts. A separate budget for *.live.test.ts would not have covered it, because
weather.test.ts is a unit test.

A bound that a client depends on is asserted by its own test, as failure.test.ts does for connect
and handshake timeouts. This setting does not carry one.

Mutations

Temporary probe tests, removed afterwards, and the config restored from a copy kept beside it:

Case Result
P1: a test sleeping 6 s, with the 30 s budget passes
C1 (control): a test sleeping 31 s, with the 30 s budget fails, "Test timed out in 30000ms"
M1: the 6 s test with testTimeout removed fails, "Test timed out in 5000ms"

C1 is the one that must keep failing: the detector still fires.

Tests

  • make check with both live engines on 211c9ab (this branch rebased on docs: the documents describe the 0.1.0 release; main moves to 0.1.1.dev0 #98):
    • ruff and mypy are clean;
    • Python: 2101 passed and 10 skipped (the orderbook slice);
    • TypeScript: 999 of 999.
  • CI: python (3.12) failed on its first attempt, in
    test_the_build_budget_bounds_a_held_build_and_recovery_finishes_it[postgres], with "tuple
    concurrently updated" from a DROP INDEX CONCURRENTLY during recovery. That is a race in the
    index operator's PostgreSQL recovery. It is on main too, and nothing here touches Python. It
    now reproduces deterministically and is fixed in its own pull request. The rerun of that job
    passed, and all fourteen checks are green.

🤖 Generated with Claude Code

vitest's default budget of 5 s is a hang detector, and on this workstation it
reported four tests as failed that were not hung. Each takes 0.4 to 1.7 s on an
idle machine and went over 5 s while another session's build and tests held the
load average at 8 on four threads: an uncertain absent batch in weather.test.ts,
two frozen-verification cases and the PostgreSQL historical-epoch copy in
generation-migration.

A hung test never finishes, so the number only decides how long it takes to say
so. Tests that name their own budget keep it, and bounds a client depends on
are asserted by their own tests, as in failure.test.ts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@krzysztof-smartdataengines
krzysztof-smartdataengines merged commit ec82f6e into main Sep 27, 2026
23 of 24 checks passed
@krzysztof-smartdataengines
krzysztof-smartdataengines deleted the test/vitest-hang-budget branch September 27, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant