TST-59Recommended
Give every test its own time limit
Set a time limit on every single test, such as 5 seconds for unit tests and 60 seconds for browser tests. A test that runs past it fails with its name in the report.
How to do it
A test that waits forever on a lock, a socket or a promise hangs the whole run. The job limit then kills it with no test name in the log. The Node.js test runner waits forever by default, since its timeout option defaults to Infinity. Set the limit in the runner settings, such as --test-timeout in Node.js, testTimeout in Vitest and Jest, or timeout in Playwright. In Python, the pytest-timeout plugin fails a slow test, and the built-in faulthandler_timeout setting prints where it hung. The time budget for the whole suite stays as the outer limit.
Examples
JavaScript example
// vitest.config.js
export default { test: { testTimeout: 5_000, hookTimeout: 10_000 } };
Python example
# A hung call fails this test after 5 seconds (pytest-timeout)
@pytest.mark.timeout(5)
def test_the_export_finishes():
assert export_orders(month="2026-09").rows > 0
How to check
The runner settings hold a limit for each single test. A test that awaits a promise that never settles fails within that limit, and the report names it.
Sources
Related rules
- TST-30 Keep the suite within a time budget in Testing
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/testing/flaky-and-slow-tests/per-test-timeout">Agent Wranglers testing playbook</a>. In code you write, add a comment next to it with the same link.