ADR-0004: Vitest as test runner
ADR-0004: Vitest as test runner
Section titled “ADR-0004: Vitest as test runner”Status: Accepted Date: 2026-04-20
Context
Section titled “Context”We need a test runner that works across a TypeScript monorepo, handles ESM cleanly, starts fast enough for tight inner-loop iteration, and extends to Cloudflare Workers when we eventually test Worker-bound code.
Decision
Section titled “Decision”Use Vitest 3 as the test runner, configured at the repository root (vitest.config.ts). Tests colocate with source as *.test.ts.
Consequences
Section titled “Consequences”- Native ESM and TypeScript. No Babel/ts-jest transform pipeline to maintain.
- Familiar API surface (
describe,it,expect) — trivial for anyone coming from Jest. @cloudflare/vitest-pool-workersexists for the day we write Worker-targeted tests; same runner, different environment.- Watch mode and HMR-style test reruns are extremely fast.
- Vitest moves quickly. Breaking changes between minors are more common than with Jest. Mitigated by pinning the exact version.
--passWithNoTestsis needed on a fresh scaffold to avoid exit-1 on empty test-globs. Enabled by default in our scripts.
Alternatives considered
Section titled “Alternatives considered”- Jest: slower on TS/ESM, larger config surface, transform pipeline overhead. The ecosystem is increasingly migrating away.
- Node built-in test runner (
node --test): minimal, standard-library-only, no mocking/spying primitives, no watch mode worth using. Fine for very small libraries; not enough for us. - Bun test: fast, clean API, but ties us to Bun as a runtime for development. Rejected alongside Bun workspaces (ADR-0001).
- Playwright for everything: rejected — overkill and slow for non-browser unit tests. We’ll reach for Playwright when we have a UI to test.