Test Runners — Vitest & Unit Testing
Test Runners — Vitest & Unit Testing: Vitest is like a teacher checking every assignment in the class at once, but only re-reading the pages that actually changed — sheets unchan
Vitest is like a teacher checking every assignment in the class at once, but only re-reading the pages that actually changed — sheets unchanged since the last check aren't read from scratch again; only the touched files get rescanned (watch mode), and results show up in seconds as ✅/❌. So if Jest is already an established test runner, why did a new tool like Vitest need to exist? Because Jest runs TypeScript files through a separate compile step first (usually Babel or ts-jest), and that creates a noticeable slowdown on large projects; Vitest instead reuses the esbuild-based instant compilation that Vite already runs internally, shrinking that step to nearly zero — the closest Java analogy is Maven doing incremental compilation instead of rebuilding the entire project every time. The concrete QA payoff: in a TypeScript project with hundreds of test files, changing just one file makes Vitest's watch mode re-run only the relevant tests within seconds; the same scenario under Jest can feel noticeably slower because of that compile step.
Vitest: The Vite-Native Test Runner
Playwright Test already ships its own test runner for end-to-end browser tests — you don't need Vitest for that. But the moment you write a plain TypeScript helper function (a price formatter, a data parser, a custom wait utility), you want to unit test that function in isolation, without spinning up a browser. That's where Vitest comes in: a fast, Jest-compatible test runner built on top of Vite, with zero-config TypeScript support. Jest is the older, more established alternative — same API shape (describe, it, expect), slower startup, and requires ts-jest to understand TypeScript out of the box.
Unit test flow with Vitest
Vite-based ultra-fast test runner — describe/it/expect API identical to Jest
describe for group, it for single test, expect for assertion — use all three layers
npx vitest run runs once for CI; npx vitest watch is for development mode
Order the steps of testing a function with Vitest:
Import the function to test
Define test group with describe
Write scenario with it and verify with expect
Run tests with npx vitest run
it('errors on negative input', () => { expect(() => formatPrice(-50)).toThrow('...') }) — why does expect wrap a function?
To catch code that throws — direct call would crash the test