Testing Mobile Apps (Jest, Testing Library, Maestro & AI QA)

Test an AI-built Expo app: unit and component tests with Jest and Testing Library, end-to-end flows with Maestro, and AI-assisted QA checklists and prompts.

AI agents write code fast and tests faster, but only tests you understand protect you. A small, layered test suite is the safety net that lets you keep prompting without fear of breaking earlier screens.

Core concepts

  1. The testing pyramid: Many fast unit tests for logic, some component tests for screens, and a few end-to-end flows for the critical paths (sign-in, core action, purchase). — React Native testing
  2. Jest with jest-expo: Jest runs unit tests in Node using the jest-expo preset, which mocks native modules so tests are fast. — Expo unit testing
  3. React Native Testing Library: Render components and query them like a user would, by text or role, then press and type. It tests behaviour instead of implementation details. — RNTL docs
  4. End-to-end with Maestro: Maestro drives a real build with simple YAML flows: launch, tap, type, assert. It is easy for agents to write and for you to read. — Maestro
  5. Detox as an alternative: Detox is a grey-box E2E framework with deeper synchronisation but more setup. Choose it if you need that control. — Detox
  6. AI-assisted QA: Use agents to generate test cases from your spec, write edge-case tests and produce manual QA checklists, then run and review them yourself. — Cursor docs
  7. Device matrix and manual QA: Test at least one small and one large iPhone, a low-end and a recent Android phone, light and dark mode, and poor network conditions. — React Native debugging

Concept videos

YouTube channels and searches for these topics. On a large screen they open in the reading panel next to the roadmap.

Explanation

Test behaviour, not implementation

Assert what the user sees and does ('Add' then count shows 1), not internal state variable names. Behavioural tests survive refactors, including ones an agent makes.

Make the agent write tests first

Ask for a failing test before the feature, then implementation, then a passing run. This keeps the agent honest and gives you a spec you can read.

Critical path first

Do not chase coverage numbers. Cover sign-in, the one thing your app exists to do, and anything involving money or data deletion.

What Is It?

Testing is running the app's logic and flows automatically to check that they behave as expected.

Layered tests catch regressions at different costs.

Why Should I Care?

Without tests every new prompt risks silently breaking an earlier feature, and you only find out from one-star reviews.

Real World Analogy

Tests are the smoke detectors, sprinklers and fire drills of a building: cheap sensors everywhere, a few full evacuations of the important exits.

Visual Mental Model

text
Unit (many, fast)
  Component (some)
    E2E on a real build (few, critical)

Beginner Explanation

Add Jest and Testing Library, write a failing test for one function, make it pass, then add one Maestro flow for sign-in.

Smallest Possible Example

tsx
import { render, screen, fireEvent } from '@testing-library/react-native';
import Counter from '../Counter';

test('increments the count', () => {
  render(<Counter />);
  fireEvent.press(screen.getByText('Add'));
  expect(screen.getByText('1')).toBeTruthy();
});

Common Mistakes

❌ Letting the agent write tests that only mirror the implementation.

Check that tests would fail if the behaviour broke.

❌ Snapshot-testing everything.

Large snapshots are approved without reading; assert specific outcomes.

❌ Only testing in the simulator.

Add real-device runs for permissions, keyboard and performance.

Real Project Example

Teams commonly pair Jest and Testing Library for fast checks with Maestro or Detox for a handful of E2E flows run in CI.

Build This Mini Project

Write tests for one utility, one component and one Maestro flow covering sign-in, and run them from a single npm script.

Interview Question

What should an end-to-end test cover in a mobile app?

Only the critical user journeys (sign-in, the core action, purchase) on a real build, because E2E tests are slower and more brittle than unit and component tests.

Key Takeaways

  • Layer your tests: unit, component, a few E2E.
  • Test behaviour, not implementation.
  • Get a failing test before the feature.
  • Cover critical paths and test on real devices.

Stack for this step

LayerPickWhy
Unit/componentJest + jest-expo + Testing LibraryFast, behavioural.
E2EMaestro (or Detox)Real builds, readable flows.
CIGitHub ActionsRun checks on every pull request.

Prompts for Cursor, Claude Code & Codex

Paste these into Cursor, Claude Code, Codex, or any coding agent. Replace the bracketed parts with your app details, and keep the agent in plan mode first so you review the approach before it edits files.

Tests from the spec

text
From SPEC.md, list the critical user journeys and for each propose test cases (happy path, empty state, error, offline). Mark which are unit, component or E2E. Do not write code yet.

Test first

text
Write failing Testing Library tests for the [feature] behaviours listed above using jest-expo. Run them to confirm they fail for the right reason, then wait for my approval before implementing.

Mutation sanity check

text
For these tests, describe one small bug in the implementation that each test would catch. Flag tests that would still pass if the feature were broken.

Claude Code skill for this step

Save this as .claude/skills/test-first/SKILL.md in your project so Claude Code loads it automatically when the task matches. The same text works as a Cursor rule or an AGENTS.md section.

text
---
name: test-first
description: Use when adding or changing behaviour, to write tests before or alongside implementation.
---
1. Write behaviour tests that fail first.
2. Implement the smallest change to pass.
3. Run the full test script, typecheck and lint.
4. Report what is covered and what is only verified manually.

Rules, databases & blogs to use

Resources

The 60-second story

A building has smoke detectors in every room, sprinklers in the halls and an occasional full evacuation drill. The detectors are cheap and fire all day; the drill is expensive so you do it for the exits that matter.

Unit tests are the detectors, component tests the sprinklers, Maestro flows the drills. When your agent rebuilds the kitchen at midnight, something goes off if it knocked out the exit. You still read the alarm panel yourself.

Mental model: cheap sensors everywhere, drills for the exits.

Threads in the same domain as this chapter — go deeper on iHateReading without leaving the roadmap.

Making AI applications without AI slop cover

Making AI applications without AI slop

Quality and safety guardrails for AI-built software.

Cursor, Codex, Claude Code prompts collection cover

Cursor, Codex, Claude Code prompts collection

200+ copy-paste prompts for coding agents to build better products.