10.5 — Vitest hands-on
You’ve been hand-rolling PASS/FAIL prints. Time to meet the professional version: Vitest — a test runner: a Node program whose entire job is to find your tests, run them in isolation, and report red or green. Watch how many of your Phase 8–9 lessons converge on this one tool: it arrives via npm, lives in devDependencies, runs on Node, and reports through exit codes.
And in the exercise you’ll build the runner itself — ten lines, thanks to 5.8 — so it never feels like magic.
// tax.test.js — the .test. marks it
import { describe, it, expect } from "vitest";
import { withTax } from "./tax.js";
describe("withTax", () => {
it("adds 25% tax", () => {
expect(withTax(100)).toBe(125);
});
it("keeps zero at zero", () => {
expect(withTax(0)).toBe(0);
});
});
// $ npm run test
// ✓ withTax > adds 25% tax
// ✗ withTax > keeps zero at zero
// Expected: 0 · Received: 1
// at tax.test.js:11:26
// Tests 1 passed | 1 failedDefinition first: a test RUNNER is a program that finds test files, executes every test in them (keeping tests isolated from each other), and reports results — human-readable ✓/✗ for you, an exit code for machines. Vitest is one; Playwright ships another. The concept is identical.
The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”
Why “Vitest”? It’s built on Vite — the same build tool running THIS app — which is where its speed comes from: tests re-run in milliseconds because Vite only re-processes what changed. Its API is deliberately compatible with Jest (the older, most famous runner), so Jest tutorials mostly apply verbatim: it and test are literally aliases.
“Runs each test in isolation” is a real promise with machinery behind it: each test file gets a fresh module environment, and hooks like beforeEach reset shared state between tests — so test 3 can’t be poisoned by test 2’s leftovers. (Phase 11’s fixtures are this idea, upgraded to whole browser contexts.)
The full report vocabulary you’ll meet: skipped (it.skip — deliberately off), todo (a named intention with no body yet), and it.only — run JUST this one while debugging. The.only left in by accident is a classic disaster (the suite silently shrinks to one test and everything “passes”); 11.13 shows the CI guard against it.
Job note: in interviews, “walk me through what happens when you run npm test” is a systems question in disguise. You can now answer it end to end: npm resolves the script (8.2) → Node launches the runner (9.1) → it globs for .test. files → runs each it, catching assertion throws (5.8, as your exercise proves) → prints ✓/✗ + summary → exits 0 or 1 → CI reads the number (9.2). Thirteen lessons in one sentence.
⌨️ build the runner itself
The starter ships a throwing assert (5.8!) and a deliberately sick withTax. Do NOT fix the bug — your job is the RUNNER: run every test, survive the failures, report the truth, hand back the exit code.
requirements:
- Keep the starter as is. Build
tests: an array of two objects, each{ name, fn }—"adds 25% tax"assertingwithTax(100)is125, and"keeps zero at zero"assertingwithTax(0)is0. - The runner: loop the tests (for...of); call each
fn()inside try/catch (5.8) — a throw means FAIL, print✗ name — message(the error object carries the message); no throw means PASS, print✓ name. Count both. - After the loop, print the summary
1 passed, 1 failed(from your counters), thenexit code: 1— computed from the fail count, 9.2’s contract.
when you press RUN, the console must show exactly:
✏️ Quick check 1
How does Vitest know which files contain tests?
✏️ Quick check 2
A suite finishes with 1 failed test. What exit code does the runner hand back?
✏️ Quick check 3
Which feature re-runs your tests automatically every time you save a file?
🗣️ Now teach it back
Walk a friend through “what actually happens when I run npm run test” — from npm to the exit code — and then explain how the runner survives a failing test without stopping (your exercise knows).
Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.