Part 9 · 2 chapters · ~12 min

Testing

From static checks to production: the trophy and the pyramid, unit, integration and end-to-end tests, doubles and MSW, contracts, visual and accessibility tests, flakes, and testing with real traffic.

20

Kinds of tests

What each kind of test is for and where it sits in the portfolio.

Testing trophy

end-to-endfew,…integrationmost…unitpure…statictype…

A test portfolio weighted toward integration tests, on a base of static checks, with fewer unit and end-to-end tests at the edges.

in practiceKent C. Dodds' alternative to the test pyramid for UI code; most confidence per minute from integration tests.

deep dive: Architecture P2

Unit test

test('formats kobo as naira', () => { expect(formatNGN(150000)).toBe('₦1,500.00');});

A test of one function or module in isolation, fast and deterministic.

in practiceFormatters, reducers, validators, money arithmetic; Vitest or Jest.

deep dive: Architecture P2

Integration test (component)

render <…user typ…userEventMSW answ…mock APIassert s…

A test rendering a component with its real children and a mocked network, driven like a user.

in practiceTesting Library + MSW; "fill the form, click pay, see the receipt".

End-to-end test

browserPlaywrightpreview URLreal appreal or seed…

A test driving a real browser through the deployed app, from login to the outcome.

in practicePlaywright and Cypress suites against preview deployments; the critical-path smoke tests.

deep dive: Architecture P2

Testing Library

getByRolerole + accessible namegetByLabelTextform fieldsgetByTextnon-interactive textgetByTestIdlast resort

Helpers that query the DOM the way users and assistive tech find things (by role, label, text), not by implementation details.

in practicegetByRole("button", {name: /pay/i}); tests that survive refactors and double as accessibility checks.

deep dive: React P12

Mock Service Worker

componentfetchMSWGET /api/cartintercepted{ items: [...] }

Intercepting network requests at the network layer with handlers, so tests and dev use the real fetch code against fake responses.

in practiceMSW handlers shared by tests, Storybook and local development.

deep dive: Architecture P2

Test double (mock, stub, spy, fake)

stubreturns canned dataspyrecords callsmockasserts callsfakeworking lightweight version

Stand-ins for real dependencies: stubs return canned values, spies record calls, mocks assert expectations, fakes are working light implementations.

in practicevi.fn(), an in-memory repository, a fake clock.

deep dive: Architecture P2

Fake timers

vi.useFakeTimers();search("pay");vi.advanceTimersByTime(300);expect(fetch).toHaveBeenCalledOnce();

Replacing setTimeout, Date and friends with a controllable clock so time-based code can be tested instantly and deterministically.

in practiceDebounce, retries with backoff, session expiry tests.

deep dive: Architecture P2

Snapshot test

big snapshot400 lines of DOM"update all"tests nothinginline, smalltoMatchInlineSnapshotone valuereviewed

Saving serialised output and failing when it changes; cheap to write, easy to rubber-stamp.

in practiceLarge component snapshots updated blindly; small inline snapshots for serialisers are fine.

deep dive: Architecture P2

Contract test

frontendcontractbackendexpects shapeverifies shapeCI fails on drift

Checking that a consumer and provider agree on an API's shape, so frontend and backend can change independently without breaking each other.

in practicePact; OpenAPI schemas validated in both repos; generated typed clients.

deep dive: Architecture P2

Property-based test

fc.assert(fc.property(fc.array(fc.integer()), xs => sum(xs) === sum([...xs].reverse())));// failure shrinks to e.g. [1, -1]

Generating many random inputs to check that a property always holds, and shrinking failures to the smallest example.

in practicefast-check for parsers, money math, sorting, CRDT merges.

deep dive: Architecture P2

Mutation testing

if (amt > limit)originalif (amt >= limit)mutant killed ✓return fee * 1mutant survived ✗

Changing the code in small ways (flipping a > to >=) and checking that some test fails; surviving mutants mark untested logic.

in practiceStryker; a better signal than line coverage for critical code.

deep dive: Architecture P2
THE TESTING LAYER, IN ORDER
from static checks to production, each kind of test where it earns its cost
swipe the figure sideways, or tap expand for full screen
1/6
portfolio
Portfolio: the trophy weights integration tests for UI; coverage maps what is untested; mutation testing checks the tests themselves.
21

Visual, browser and production

Tests that need a browser, a screenshot or real traffic, and the problems they bring.

Visual regression test

baselineapprovedbutton 40pxthis PR0.8% pixels differbutton 44px

Screenshotting components or pages and diffing them against approved baselines to catch unintended visual changes.

in practiceChromatic, Playwright toHaveScreenshot, Percy; design-system PRs.

Storybook

Button/PrimaryButton/LoadingButton/DisabledInput/ErrorInput/FilledModal/Open

A workshop for rendering components in isolation with their states as stories, which double as docs and test cases.

in practiceDesign-system catalogues; stories run as interaction and visual tests.

deep dive: Design P7

Flaky test

✓✓✗✓✓✓✗✓✓✓✓✗same commit, different results

A test that passes and fails without code changes, from timing, order dependence, shared state or real network.

in practiceRetries hiding races; quarantine lists; the main destroyer of trust in CI.

Code coverage

covereduntested78% linesexecuted is not the same as asserted

The share of lines, branches or functions executed by tests; a map of what is untested, not a measure of quality.

in practiceIstanbul and V8 coverage reports; coverage gates that encourage assertion-free tests.

deep dive: Architecture P2

Test isolation

shared statetest B relies on Aorder mattersflaky in parallelisolatedeach test sets upany orderparallel-safe

Each test sets up its own state and does not depend on others or on order, so tests can run in parallel and in any sequence.

in practiceLeaking module state between tests; fresh QueryClient per test.

deep dive: Architecture P2

Test fixture and factory

const user = buildUser({ kycTier: 2 });const order = buildOrder({ user, total: 150000 });// everything else: valid defaults

Reusable setup data and builders that create valid objects with overridable fields.

in practicebuildUser({ kycTier: 2 }); Playwright fixtures for logged-in pages.

deep dive: Architecture P2

Accessibility test (automated)

automatableneeds a humanaxe catches about a third

Running axe-core rules in unit, component or end-to-end tests to catch roughly a third of WCAG failures automatically.

in practicejest-axe, @axe-core/playwright, Storybook a11y addon; the rest needs manual passes.

deep dive: Disciplines P3

Lighthouse CI

LCP2.1 s ≤ 2.5 ✓TBT310 ms > 200 ✗CLS0.02 ≤ 0.1 ✓JS bytes182 KB ≤ 200 ✓

Running Lighthouse against previews in CI with assertions on scores and metrics, failing PRs that regress.

in practiceMedian of three runs; budgets on LCP, TBT, CLS and bytes.

Smoke test

deploysmokelogin, paytrafficif green

A small, fast check that the most important paths work after a deploy, before deeper tests or traffic.

in practicePost-deploy login, search and checkout checks; synthetic monitors every few minutes.

deep dive: Architecture P2

Test in production

flag on 1%watch RUM, e…ramp or roll…

Verifying behaviour with real traffic under control: canaries, feature flags, synthetic monitors and RUM alerts.

in practiceThe ring halt on a crash-free drop; dark launches.

Arrange, act, assert

// arrangerender(<Cart items={[pen]} />);// actawait user.click(screen.getByRole('button', { name: /…// assertexpect(screen.getByText(/empty/i)).toBeVisible();

The three-part shape of a readable test: set up, do one thing, check the outcome.

in practiceTests that read like specifications; one behaviour per test.

deep dive: Architecture P2

Test pyramid

e2efewintegrationsomeunitmany

The classic portfolio shape: many unit tests, fewer integration tests, few end-to-end tests, ordered by speed and cost.

in practiceBackend services; contrasted with the trophy for UI.

deep dive: Architecture P2