पाठ 22 / 25

Organising Tests and Test Data Factories

Where tests live and how to build data.

Colocate tests, centralise helpers

Most frontend projects colocate tests next to the code (Button.tsx and Button.test.tsx) so they move together, and keep shared helpers in one place such as src/test/ (setup file, MSW handlers, custom render, factories). Name files consistently so the runner's include pattern finds them. For data, use factories: small functions that return a valid object with sensible defaults and accept overrides, so each test states only the fields it cares about. Factories avoid giant shared fixture files that every test silently depends on, and keep types honest because they return the real TypeScript type. Libraries such as @faker-js/faker or fishery can help, but a typed function is often enough; avoid random data unless you seed it.

A suite the whole team trusts

A healthy suite is organised, fast, deterministic and runs on every change in CI.

Three ideas: organisation and factories, flaky tests and debugging, CI; plus a checklist.
Figure 8.1 — Organise tests, debug flakiness, run everything in CI.

A typed factory with overrides

Each test states only what matters.

// src/test/factories.ts
import type { Order, User } from '../types';

let seq = 0;
const nextId = (prefix: string) => `${prefix}_${++seq}`;

export function buildUser(overrides: Partial<User> = {}): User {
  return { id: nextId('u'), name: 'Test User', email: 'user@example.com', role: 'member', ...overrides };
}

export function buildOrder(overrides: Partial<Order> = {}): Order {
  return { id: nextId('o'), userId: buildUser().id, items: [], status: 'pending', totalCents: 0, ...overrides };
}

// in a test: only the relevant field is visible
// const admin = buildUser({ role: 'admin' });
// const shipped = buildOrder({ status: 'shipped', totalCents: 4200 });

// project layout
// src/components/Button.tsx
// src/components/Button.test.tsx
// src/test/{setup.ts, server.ts, handlers.ts, test-utils.tsx, factories.ts}

Make the important value obvious

If a test is about admins, write buildUser({ role: 'admin' }) in the test even if admin were the default. Readers should not need to open the factory to understand why a test passes.

त्वरित जाँच: What is the main benefit of a test data factory with overrides?

  • It replaces MSW handlers
  • It removes the need for assertions
  • It makes data random on every run
  • Tests specify only the fields they care about while still getting valid objects
Answer

Tests specify only the fields they care about while still getting valid objects — Defaults plus overrides keep tests short and explicit.