The smallest useful unit test: no I/O, no mocks, one behavior. Compare how Vitest, Jest, Node's built-in test runner, and pytest express the same idea.
Vitest · Unit / component test runner (Vite-native) · MIT
Vitest is a fast test runner for JavaScript and TypeScript. Its API matches Jest (describe, it, expect, vi.fn), so teams can move between the two with little rewrite. It runs in Vite’s transform pipeline, which keeps ESM and modern syntax cheap.
A runner process loads each test file, executes describe/it blocks, and reports pass/fail. Assertions come from expect(). The SUT is imported as a normal module — no HTTP server, no browser. Mocks live on vi (vi.fn, vi.mock).
Testing architecture
Unit tests call one function (or a small graph of functions) in the same process. They avoid I/O so failures point at logic, not the environment. The SUT is imported; the runner never starts Express or a browser.
Import a pure add() function and assert 2 + 3 === 5. The runner, assertion API, and SUT share one process. Nothing is mocked and no port is opened — if this fails, the function (or the assertion) is wrong.
SUT: js-counter / python-calc · samples/js-counter/src/index.js · run npm test in examples/unit/assert-equality/vitest
Code under test · samples/js-counter/src/index.js
/** Tiny shared system under test for unit/UX demos. */
/**
* Add two numbers and return their sum.
* @param {number} a - First operand
* @param {number} b - Second operand
*/
export function add(a, b) {
// Pure arithmetic — no I/O, no side effects
return a + b;
}
/**
* Keep n inside the inclusive range [min, max].
* @param {number} n - Value to clamp
* @param {number} min - Lower bound
* @param {number} max - Upper bound
*/
export function clamp(n, min, max) {
// Guard: a flipped range is a caller bug, not a silent no-op
if (min > max) {
throw new Error("min must be <= max");
}
// Raise floor first, then lower the ceiling
return Math.min(max, Math.max(min, n));
}
/**
* Apply a region tax rate from an injected service.
* @param {{ getTaxRate: (code: string) => number }} taxService - Collaborator that owns tax rates
* @param {number} amount - Pre-tax amount
* @param {string} region - Region code passed to the tax service
*/
export function priceWithTax(taxService, amount, region) {
// Ask the dependency for the rate (easy to mock in unit tests)
const rate = taxService.getTaxRate(region);
// Gross = net × (1 + rate), e.g. 100 at 10% → 110
return amount * (1 + rate);
}
/**
* Apply a published checkout coupon to a subtotal.
* Grown via TDD in unit.tdd-red-green (this scenario only — BDD uses reserveRoom).
* @param {number} subtotal - Cart total before the coupon
* @param {string} [coupon] - Published code, or empty / unknown
*/
export function applyCoupon(subtotal, coupon) {
if (typeof subtotal !== "number" || subtotal < 0) {
throw new Error("subtotal must be a non-negative number");
}
// SAVE10: always 10% off
if (coupon === "SAVE10") {
return subtotal * 0.9;
}
// SAVE20: 20% off only when the cart is at least 50
if (coupon === "SAVE20" && subtotal >= 50) {
return subtotal * 0.8;
}
// Missing, unknown, or SAVE20-below-minimum → pay the original subtotal
return subtotal;
}
/**
* Reserve seats in a meeting room.
* Specified in Gherkin in unit.bdd-given-when-then (this scenario only — TDD uses applyCoupon).
* @param {number} partySize - Guests who want the room
* @param {number} seatsFree - Seats still open
* @returns {{ confirmed: boolean, seatsFree: number }}
*/
export function reserveRoom(partySize, seatsFree) {
if (typeof partySize !== "number" || partySize < 1) {
throw new Error("partySize must be at least 1");
}
if (typeof seatsFree !== "number" || seatsFree < 0) {
throw new Error("seatsFree must be a non-negative number");
}
if (partySize > seatsFree) {
return { confirmed: false, seatsFree };
}
return { confirmed: true, seatsFree: seatsFree - partySize };
}
Test · examples/unit/assert-equality/vitest/add.test.js · MIT
· run in examples/unit/assert-equality/vitest: npm test
// Bring in Vitest's suite helpers and assertion API
import { describe, it, expect } from "vitest";
// Import the pure function under test from the shared sample
import { add } from "../../../../samples/js-counter/src/index.js";
// Group related examples under one describe block
describe("add", () => {
// One concrete behavior: 2 + 3 should equal 5
it("returns the sum of two numbers", () => {
// Call the SUT, then assert exact equality with toBe
expect(add(2, 3)).toBe(5);
});
});
Jest is the long-standing default runner in many Node and React codebases. It bundles a runner, assertion library, mocking (jest.fn), and snapshot testing. This repo uses ESM via NODE_OPTIONS=--experimental-vm-modules.
Jest discovers test files, wraps them in a VM, and provides describe/it/expect as globals (or via @jest/globals in ESM). The SUT is imported in-process. Isolation is per-file by default, not a real network hop.
Testing architecture
Unit tests call one function (or a small graph of functions) in the same process. They avoid I/O so failures point at logic, not the environment. The SUT is imported; the runner never starts Express or a browser.
Import a pure add() function and assert 2 + 3 === 5. The runner, assertion API, and SUT share one process. Nothing is mocked and no port is opened — if this fails, the function (or the assertion) is wrong.
SUT: js-counter / python-calc · samples/js-counter/src/index.js · run npm test in examples/unit/assert-equality/jest
Code under test · samples/js-counter/src/index.js
/** Tiny shared system under test for unit/UX demos. */
/**
* Add two numbers and return their sum.
* @param {number} a - First operand
* @param {number} b - Second operand
*/
export function add(a, b) {
// Pure arithmetic — no I/O, no side effects
return a + b;
}
/**
* Keep n inside the inclusive range [min, max].
* @param {number} n - Value to clamp
* @param {number} min - Lower bound
* @param {number} max - Upper bound
*/
export function clamp(n, min, max) {
// Guard: a flipped range is a caller bug, not a silent no-op
if (min > max) {
throw new Error("min must be <= max");
}
// Raise floor first, then lower the ceiling
return Math.min(max, Math.max(min, n));
}
/**
* Apply a region tax rate from an injected service.
* @param {{ getTaxRate: (code: string) => number }} taxService - Collaborator that owns tax rates
* @param {number} amount - Pre-tax amount
* @param {string} region - Region code passed to the tax service
*/
export function priceWithTax(taxService, amount, region) {
// Ask the dependency for the rate (easy to mock in unit tests)
const rate = taxService.getTaxRate(region);
// Gross = net × (1 + rate), e.g. 100 at 10% → 110
return amount * (1 + rate);
}
/**
* Apply a published checkout coupon to a subtotal.
* Grown via TDD in unit.tdd-red-green (this scenario only — BDD uses reserveRoom).
* @param {number} subtotal - Cart total before the coupon
* @param {string} [coupon] - Published code, or empty / unknown
*/
export function applyCoupon(subtotal, coupon) {
if (typeof subtotal !== "number" || subtotal < 0) {
throw new Error("subtotal must be a non-negative number");
}
// SAVE10: always 10% off
if (coupon === "SAVE10") {
return subtotal * 0.9;
}
// SAVE20: 20% off only when the cart is at least 50
if (coupon === "SAVE20" && subtotal >= 50) {
return subtotal * 0.8;
}
// Missing, unknown, or SAVE20-below-minimum → pay the original subtotal
return subtotal;
}
/**
* Reserve seats in a meeting room.
* Specified in Gherkin in unit.bdd-given-when-then (this scenario only — TDD uses applyCoupon).
* @param {number} partySize - Guests who want the room
* @param {number} seatsFree - Seats still open
* @returns {{ confirmed: boolean, seatsFree: number }}
*/
export function reserveRoom(partySize, seatsFree) {
if (typeof partySize !== "number" || partySize < 1) {
throw new Error("partySize must be at least 1");
}
if (typeof seatsFree !== "number" || seatsFree < 0) {
throw new Error("seatsFree must be a non-negative number");
}
if (partySize > seatsFree) {
return { confirmed: false, seatsFree };
}
return { confirmed: true, seatsFree: seatsFree - partySize };
}
Test · examples/unit/assert-equality/jest/add.test.js · MIT
· run in examples/unit/assert-equality/jest: npm test
// Import the pure function under test from the shared sample
import { add } from "../../../../samples/js-counter/src/index.js";
// Group related examples under one describe block (Jest globals)
describe("add", () => {
// One concrete behavior: 2 + 3 should equal 5
it("returns the sum of two numbers", () => {
// Call the SUT, then assert exact equality with toBe
expect(add(2, 3)).toBe(5);
});
});
node:test ships with Node — no extra test-framework dependency. You import describe/it from node:test and assert from node:assert/strict. Output is TAP-like diagnostics on the CLI.
node --test loads files, runs each it() as a test, and fails the process on the first assertion throw. There is no built-in expect() matcher DSL; equality is assert.equal. The SUT is still a direct import.
Testing architecture
Unit tests call one function (or a small graph of functions) in the same process. They avoid I/O so failures point at logic, not the environment. The SUT is imported; the runner never starts Express or a browser.
Import a pure add() function and assert 2 + 3 === 5. The runner, assertion API, and SUT share one process. Nothing is mocked and no port is opened — if this fails, the function (or the assertion) is wrong.
SUT: js-counter / python-calc · samples/js-counter/src/index.js · run npm test in examples/unit/assert-equality/node-test
Code under test · samples/js-counter/src/index.js
/** Tiny shared system under test for unit/UX demos. */
/**
* Add two numbers and return their sum.
* @param {number} a - First operand
* @param {number} b - Second operand
*/
export function add(a, b) {
// Pure arithmetic — no I/O, no side effects
return a + b;
}
/**
* Keep n inside the inclusive range [min, max].
* @param {number} n - Value to clamp
* @param {number} min - Lower bound
* @param {number} max - Upper bound
*/
export function clamp(n, min, max) {
// Guard: a flipped range is a caller bug, not a silent no-op
if (min > max) {
throw new Error("min must be <= max");
}
// Raise floor first, then lower the ceiling
return Math.min(max, Math.max(min, n));
}
/**
* Apply a region tax rate from an injected service.
* @param {{ getTaxRate: (code: string) => number }} taxService - Collaborator that owns tax rates
* @param {number} amount - Pre-tax amount
* @param {string} region - Region code passed to the tax service
*/
export function priceWithTax(taxService, amount, region) {
// Ask the dependency for the rate (easy to mock in unit tests)
const rate = taxService.getTaxRate(region);
// Gross = net × (1 + rate), e.g. 100 at 10% → 110
return amount * (1 + rate);
}
/**
* Apply a published checkout coupon to a subtotal.
* Grown via TDD in unit.tdd-red-green (this scenario only — BDD uses reserveRoom).
* @param {number} subtotal - Cart total before the coupon
* @param {string} [coupon] - Published code, or empty / unknown
*/
export function applyCoupon(subtotal, coupon) {
if (typeof subtotal !== "number" || subtotal < 0) {
throw new Error("subtotal must be a non-negative number");
}
// SAVE10: always 10% off
if (coupon === "SAVE10") {
return subtotal * 0.9;
}
// SAVE20: 20% off only when the cart is at least 50
if (coupon === "SAVE20" && subtotal >= 50) {
return subtotal * 0.8;
}
// Missing, unknown, or SAVE20-below-minimum → pay the original subtotal
return subtotal;
}
/**
* Reserve seats in a meeting room.
* Specified in Gherkin in unit.bdd-given-when-then (this scenario only — TDD uses applyCoupon).
* @param {number} partySize - Guests who want the room
* @param {number} seatsFree - Seats still open
* @returns {{ confirmed: boolean, seatsFree: number }}
*/
export function reserveRoom(partySize, seatsFree) {
if (typeof partySize !== "number" || partySize < 1) {
throw new Error("partySize must be at least 1");
}
if (typeof seatsFree !== "number" || seatsFree < 0) {
throw new Error("seatsFree must be a non-negative number");
}
if (partySize > seatsFree) {
return { confirmed: false, seatsFree };
}
return { confirmed: true, seatsFree: seatsFree - partySize };
}
Test · examples/unit/assert-equality/node-test/add.test.js · MIT
· run in examples/unit/assert-equality/node-test: npm test
// Node's built-in test runner — no third-party test framework
import { describe, it } from "node:test";
// Strict assert helpers (throws on failure)
import assert from "node:assert/strict";
// Import the pure function under test from the shared sample
import { add } from "../../../../samples/js-counter/src/index.js";
// Group related examples under one describe block
describe("add", () => {
// One concrete behavior: 2 + 3 should equal 5
it("returns the sum of two numbers", () => {
// Call the SUT, then assert exact equality
assert.equal(add(2, 3), 5);
});
});
pytest is the usual Python runner: files named test_*.py, functions named test_*, rich fixtures, and first-class parametrize. Assertions are plain assert statements that pytest rewrites with better diffs.
pytest collects test functions, optionally injects fixtures, and reports failures with the rewritten assertion. For unit examples here, the SUT is imported from samples/python-calc after sys.path is adjusted. No HTTP is involved.
Testing architecture
Unit tests call one function (or a small graph of functions) in the same process. They avoid I/O so failures point at logic, not the environment. The SUT is imported; the runner never starts Express or a browser.
Import a pure add() function and assert 2 + 3 === 5. The runner, assertion API, and SUT share one process. Nothing is mocked and no port is opened — if this fails, the function (or the assertion) is wrong.
SUT: js-counter / python-calc · samples/python-calc/calc.py · run pytest in examples/unit/assert-equality/pytest
Code under test · samples/python-calc/calc.py
"""Tiny Python twin of the JS counter SUT."""
from typing import Optional
def add(a: float, b: float) -> float:
# Pure arithmetic — no I/O, no side effects
return a + b
def clamp(n: float, min_value: float, max_value: float) -> float:
# Guard: a flipped range is a caller bug, not a silent no-op
if min_value > max_value:
raise ValueError("min must be <= max")
# Raise floor first, then lower the ceiling
return min(max_value, max(min_value, n))
def price_with_tax(tax_service, amount: float, region: str) -> float:
# Ask the dependency for the rate (easy to mock in unit tests)
rate = tax_service.get_tax_rate(region)
# Gross = net × (1 + rate), e.g. 100 at 10% → 110
return amount * (1 + rate)
def apply_coupon(subtotal: float, coupon: Optional[str] = None) -> float:
"""Apply a published checkout coupon. Twin of JS applyCoupon()."""
if subtotal < 0:
raise ValueError("subtotal must be a non-negative number")
# SAVE10: always 10% off
if coupon == "SAVE10":
return subtotal * 0.9
# SAVE20: 20% off only when the cart is at least 50
if coupon == "SAVE20" and subtotal >= 50:
return subtotal * 0.8
# Missing, unknown, or SAVE20-below-minimum → pay the original subtotal
return subtotal
def reserve_room(party_size: int, seats_free: int) -> dict:
"""Reserve seats. Twin of JS reserveRoom() — used only by the BDD scenario."""
if party_size < 1:
raise ValueError("partySize must be at least 1")
if seats_free < 0:
raise ValueError("seatsFree must be a non-negative number")
if party_size > seats_free:
return {"confirmed": False, "seats_free": seats_free}
return {"confirmed": True, "seats_free": seats_free - party_size}
Test · examples/unit/assert-equality/pytest/test_add.py · MIT
· run in examples/unit/assert-equality/pytest: pytest
# Make the shared Python sample importable from this example folder
import sys
from pathlib import Path
# Walk up to the repo root (parents[4] from this file)
ROOT = Path(__file__).resolve().parents[4]
# Put samples/python-calc on sys.path so `import calc` works
sys.path.insert(0, str(ROOT / "samples" / "python-calc"))
# Import the pure function under test
from calc import add
def test_add_returns_sum():
# Call the SUT, then assert exact equality with ==
assert add(2, 3) == 5
Python twin uses samples/python-calc instead of the JS module.