Arrange / Act / Assert
A structure for writing a clear unit test — set up the input, run the code under test, check the result.
Purpose
Arrange/Act/Assert structures a unit test into three clear phases, making its intent — what’s being set up, what’s being tested, what’s being checked — legible at a glance, even without comments.
Example
import { describe, it, expect } from 'vitest';
import { calculateDiscount } from './pricing.js';
describe('calculateDiscount', () => {
it('applies a percentage discount to a price', () => {
// Arrange
const price = 100;
const percentOff = 20;
// Act
const result = calculateDiscount(price, percentOff);
// Assert
expect(result).toBe(80);
});
});
The three phases
- Arrange: set up whatever the test needs — input values, in the simplest cases just a couple of variables.
- Act: call the function or code path actually under test — usually a single line.
- Assert: check the result matches what’s expected, usually with one or a small number of assertions focused on a single behavior.
Why it helps
- A test that doesn’t fit cleanly into these three phases is often testing more than one thing at once — a signal to split it into separate, more focused tests.
- Testing boundary cases (empty input, zero, the minimum/maximum of a valid range) alongside a typical case catches the class of bug a single “happy path” test would miss entirely.
Common mistakes
- Asserting many unrelated things in one test, making a failure harder to diagnose (which assertion actually failed, and why).
- Skipping boundary cases and testing only the most obvious, typical input.
Runtime notes
A testing convention, not a language or framework feature — applies identically regardless of which test runner (Vitest, Jest, and others) is in use.