react-brain
Browse decisions
React & language foundations 3App architecture 9UI 12Platform & native 9Build, test, observe, secure 6AI in React apps 3stack composerdecision recordscensusstaleness bencharchitecturechangelogmethodologyroadmap

entriestooling-ops · verified 2026-07-10 · react + react-native

Testing strategy & tooling

reviewedconfidence: highthis tier holds 75% on the public scorecard (6/11 graded · 0 overturned) →

related decisions: p2p

cited by: ai-devtools

re-verified 5× — 2026-07-13 · 2026-07-10 · 2026-07-09 · 2026-07-07 · 2026-07-06 · changelog

recommendation

Unit/component: Vitest (web) or Jest (RN) + React Testing Library. E2E: Playwright (web), Maestro (RN). MSW for API mocks; Storybook for component dev.

  • RN e2e → Maestro (Expo's recommendation; it archived Detox)
  • API-heavy tests → MSW so the same mocks serve unit + e2e + dev
  • Holepunch / Bare app → brittle (the ecosystem's TAP runner) is idiomatic, not a deviation — see RB-E-P2P
  • unit/integration tests that must exercise real NATIVE modules → react-native-harness (early; pin versions)
  • test discipline (what to test, TDD) → agentic-engineering-patterns

Options & tradeoffs

the field considered — and why each one isn’t the default here

optiontradeoffevidence
Jest / Vitestunit; Vitest faster on web, Jest default on RN35.7M/wk · ships in 22/34
React Testing Library (14)behavior-first component tests (web + RN variants); v14 adds React 19 support + async APIs46.6M/wk · ships in 14/34
MSW (Mock Service Worker)network-level API mocking; same mocks reused across unit/e2e and dev19.2M/wk · ships in 9/34
Playwright / Maestro / Detox / Meticulouse2e: Playwright web; Maestro 2.0 (AI test-healing) is Expo's recommended native e2e (Expo archived Detox; Detox has a 'Copilot' beta); Maestro now bundles an MCP server so coding agents can drive simulators/emulators/devices, inspect UI, and generate E2E flows (claude mcp add maestro -- maestro mcp); Meticulous = record-based AI e2e45.2M/wk · ships in 8/34
Storybook 10component workshop; web + RN run side-by-side; Vite 8 + Playwright/Vitest test integration + MCPships in 11/34
Radon IDE (Software Mansion)VS Code / Cursor RN debugging — device panel, click-to-inspect, React Profiler
Argent (Software Mansion) — NEW/experimentalagentic toolkit giving an AI assistant control of the iOS Simulator (drive + inspect the running app) to shorten the debug loop; new, niche
react-native-harness (Callstack) — NEWJest-style describe/it tests running ON real devices/simulators (iOS/Android/web) with native-module access — the on-device unit/integration layer between Node-Jest and black-box Maestro; v1.3 (2026-05), early36k/wk

evidence: npm weekly downloads (signals snapshot) · “ships in n/D” = adoption across the production-app census, honest denominators

Migration lines

version and deprecation lines this decision tracks — for YOUR repo's sequenced plan: the doctor or npx -y @heart-it/react-brain migrate .

react-test-renderer → React Native Testing Library v14 (host-element role/label queries) [deprecated · effort M]

react-test-renderer is deprecated by React core; RNTL v14 runs its own react-reconciler-based test renderer rendering host elements only — don't reach for react-test-renderer in new test code

github.com/mdjastrzebski/test-renderer

npm weekly downloads (from the corpus's last signals run): jest 35.7M · vitest 76.5M · @testing-library/react-native 2.5M · @testing-library/react 46.6M · @playwright/test 45.2M · detox 535k · msw 19.2M · brittle 24k · react-native-harness 36k

Verified notes

RN 0.85 (2026-04-07) moved the Jest preset out of the core package — set `preset: '@react-native/jest-preset'` in jest.config.js (was `preset: 'react-native'`). For native e2e, Expo now recommends Maestro (it archived its Detox support docs). Maestro's MCP server (verified vs docs.maestro.dev, 2026-07-07) puts device-driving + E2E-generation in the hands of coding agents — the agent-driven-testing trend consolidating around the tool the ecosystem already recommends. Jest-preset fact verified against the official RN 0.85 release blog. RENDERER FLIP (2026-07-10, verified vs the docs + the mdjastrzebski/test-renderer repo): RN Testing Library v14 (actively maintained) runs on its own react-reconciler-based test-renderer that renders HOST elements only — which is WHY its query model moved to host-element/role queries. The old react-test-renderer package from React core is deprecated — don't reach for it in new test code.

Canonical reading

Editorial annotations on why each piece matters — the articles themselves are the originals; read them there.

Test IDs are an a11y smellDominik Dorfmeister (TkDodo)

The bridge between this entry and RB-E-A11Y: querying by data-testid silently hides inaccessible markup, while role/label queries fail exactly when a real assistive-tech user would — so accessible queries are both the better test AND a free a11y audit. Sharpens the Testing-Library philosophy the two Dodds pieces establish.

Write tests. Not too many. Mostly integration.Kent C. Dodds

The foundational testing-strategy essay: maximize confidence per effort by favoring integration tests over mock-heavy unit suites and coverage-chasing. The origin of the Testing-Trophy mindset.

Testing Implementation DetailsKent C. Dodds

Why tests coupled to internals are brittle (false failures on refactor, false passes on breakage) and why to test behavior the way users use it. The mental model behind Testing Library.

Sources

Depth (in-domain rules) is owned by the agentic-engineering-patterns skill — this entry is selection breadth.

The full explanation

The reviewed long-form essay behind this entry — the why, not a how-to. Also on GitHub.

About testing strategy & tooling in React & React Native

Diataxis: Explanation. This page builds understanding of how to think about testing — the reasoning behind the tool picks. It is not a tutorial, and the discipline (what to test, TDD, how much) is owned by the agentic-engineering-patterns skill. Read this for the why.

The one idea that organises everything: confidence per effort

Don't start from "unit vs integration vs e2e." Start from the question every test silently answers: how much confidence does this buy, for how much cost to write and maintain? That ratio — not dogma about test types — is the organising principle, and it produces the Testing Trophy: a few end-to-end tests, a strong middle of integration tests, fewer isolated unit tests, with static typing/linting as the base. Integration tests dominate because they exercise real component interactions (high confidence) without the brittleness of mock- heavy unit tests or the slowness of full e2e.

Two corollaries fall straight out, and they drive the tool choices:

  • Test behaviour, not implementation. Query by role/label like a user; don't assert on internal state or reach for data-testid as a crutch. Tests coupled to internals fail on refactors (false negatives) and pass on real breakage (false positives).
  • Mock at the boundary, not the module. Stub the network, not your own functions, so the same mocks serve unit, integration, and dev.

The default, and why

Unit/component: Vitest (web) or Jest (RN) + React Testing Library. E2E: Playwright (web), Maestro (RN). MSW for API mocks; Storybook for component dev.

The platform fork is about fit, not quality: Vitest is faster and Vite-native on the web; Jest remains the RN default (note: RN 0.85 moved the preset out of core — set preset: '@react-native/jest-preset', verified against the RN 0.85 blog). React Testing Library is the constant on both because it enforces the behaviour-not-implementation rule by construction. For e2e, Playwright owns the web; Maestro is Expo's recommendation for RN (Expo archived its Detox support). MSW is the keystone that makes the Trophy practical — one set of network mocks reused across every layer and in dev.

The landscape, and when each one wins

Jest / Vitest — the unit/component runners. Vitest on the web (speed, Vite integration), Jest on RN (default, ecosystem). Pick by platform, not preference.

React Testing Library (14) — behaviour-first component testing; v14 adds React 19 support and async APIs. It's not just a tool but a philosophy enforcer — its API makes implementation- detail testing awkward on purpose.

MSW (Mock Service Worker) — network-level API mocking. The reason it matters: the same handlers serve unit tests, integration tests, e2e, and local dev — so your mocks don't drift per layer. Reach for it the moment tests are API-heavy.

Playwright / Maestro / Detox / Meticulous — the e2e tier. Playwright for web; Maestro (AI test-healing) is the RN recommendation now that Expo archived Detox; Meticulous is record-based AI e2e. E2e is the smallest, slowest, highest-confidence layer — keep it few and critical-path.

Storybook (10) — the component workshop (web + RN side by side), with Vitest/Playwright test integration. It's where component development and visual/interaction testing meet.

Radon IDE — RN debugging in VS Code/Cursor (device panel, click-to-inspect, Profiler); a DX-adjacent aid to the loop rather than a test type.

Tradeoffs and failure modes to name out loud

  • Inverting the Trophy. Piling up mock-heavy unit tests feels productive but buys little confidence and breaks on every refactor. Push effort to the integration middle.
  • Testing implementation details. data-testid everywhere, asserting on state/private methods — the canonical brittleness source. Query like a user (this also improves a11y; role queries exercise the accessibility tree — see RB-E-A11Y).
  • Mocking your own modules instead of the network. Per-test function mocks drift from reality and from each other; MSW at the boundary keeps them honest.
  • E2e as the main suite. Slow, flaky-prone, expensive to maintain. It's the thin top of the Trophy, not the body.
  • Tests that aren't gated. A suite that doesn't run in CI rots — testing tooling only pays off inside the RB-E-DX feedback loop.

How it interacts with the rest of the stack

  • DX (RB-E-DX). Tests only protect you if CI runs them on every PR; the testing tools and the CI gate are two halves of one loop.
  • Data (RB-E-DATA). MSW lets you test data-fetching behaviour against realistic network responses without hitting real servers.
  • Accessibility (RB-E-A11Y). Role/label-based queries (the RTL default) double as an a11y check; test-IDs bypass that signal.
  • Discipline (agentic-engineering-patterns). What to test, when to write tests first, and how much is owned there — this page is which tools, that skill is the practice.

In one paragraph

Choose tests by confidence per effort, which yields the Testing Trophy: a strong integration middle, few e2e, unit where isolation helps, types/lint as the base. Test behaviour, not implementation (React Testing Library enforces it) and mock the network, not your modules (MSW, reused across every layer). Tooling forks by platform — Vitest/Jest + RTL for components, Playwright (web) / Maestro (RN) for e2e — and none of it pays off unless CI runs it (RB-E-DX); the discipline of what-to-test lives in agentic-engineering-patterns.


See also: RB-E-DX (CI gates the suite), RB-E-DATA (MSW + data-fetching tests), RB-E-A11Y (role queries as an a11y signal). TDD / what-to-test discipline: the agentic-engineering-patterns skill.

Related in tooling-ops: build · dx · observability · security · ota