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.

Taught in these lessons

Updated 2026-09-03