Publié · en amélioration
Guide React Native · 5/6
Ce chapitre n'est disponible qu'en anglais pour le moment.
React Native apps are usually tested in three layers: plain logic with Jest, components with React Native Testing Library, and complete user flows on real devices with end-to-end tools such as Detox or Maestro.
| Layer | Tools | Runs on |
|---|---|---|
| Unit | Jest | Node.js |
| Component | Jest + React Native Testing Library | Node.js (rendered without native code) |
| End-to-end | Detox, Maestro | emulators, simulators, devices |
The Community CLI template ships with Jest already configured using the react-native preset. In an Expo project, add the jest-expo preset:
npx expo install jest-expo jest @types/jest -- --dev
npx expo install @testing-library/react-native -- --dev{
"scripts": {
"test": "jest --watchAll"
},
"jest": {
"preset": "jest-expo"
}
}The preset provides mocks for React Native modules and the transform setup, so all you need are test files (*.test.tsx or a __tests__ folder).
Logic that has nothing to do with the UI, such as calculations and formatting, is tested with plain Jest. Moving logic out of components into functions makes it much easier to test.
// price.ts
export const formatPrice = (cents: number) => `$${(cents / 100).toFixed(2)}`;
// price.test.ts
import { formatPrice } from "./price";
test("formats cents as dollars", () => {
expect(formatPrice(1250)).toBe("$12.50");
});React Native Testing Library (RNTL) renders a component, finds elements by the text or accessibility role a user would see, and simulates actions such as presses and typing. The guiding principle is to test what the user sees rather than implementation details.
import { render, screen, userEvent } from "@testing-library/react-native";
import { Counter } from "./Counter";
test("increments when pressed", async () => {
const user = userEvent.setup();
render(<Counter />);
expect(screen.getByText("Count: 0")).toBeOnTheScreen();
await user.press(screen.getByText("Increment"));
expect(screen.getByText("Count: 1")).toBeOnTheScreen();
});RNTL provides matchers such as toBeOnTheScreen and toHaveTextContent; older versions may require importing @testing-library/react-native/extend-expect in a setup file. Queries come in three flavors: getBy... (immediate, throws if missing), (returns null if missing) and (waits until the element appears).
queryBy...findBy...Replace network calls and native modules with mocks in tests. AsyncStorage ships an official Jest mock.
import { render, screen } from "@testing-library/react-native";
import { Posts } from "./Posts";
jest.mock("@react-native-async-storage/async-storage", () =>
require("@react-native-async-storage/async-storage/jest/async-storage-mock"),
);
test("shows posts from the server", async () => {
global.fetch = jest.fn().mockResolvedValue({
ok: true,
json: async () => [{ id: 1, title: "First post" }],
}) as jest.Mock;
render(<Posts />);
expect(await screen.findByText("First post")).toBeOnTheScreen();
});End-to-end tests run a real build of the app on an emulator or device and drive it the way a person would. Add testID props to components so tests can find them reliably.
Detox, created by Wix, is a gray-box end-to-end framework. It automatically waits for in-flight network requests and animations inside the app, which makes tests less flaky. Tests are written in JavaScript and run with Jest. Configuration lives in .detoxrc.js; Expo projects use it with a development build or prebuilt native projects.
describe("Login", () => {
beforeAll(async () => {
await device.launchApp();
});
it("shows the home screen after logging in", async () => {
await element(by.id("email")).typeText("user@example.com");
await element(by.id("login-button")).tap();
await expect(element(by.text("Welcome"))).toBeVisible();
});
});npx detox build --configuration ios.sim.debug
npx detox test --configuration ios.sim.debugConfiguration names such as ios.sim.debug are the ones you define in .detoxrc.js.
Maestro is a black-box end-to-end tool where flows are written in YAML. It drives the installed app from the outside without changes to app code, so setup is light, and it can also run in EAS Workflows. A React Native testID is matched by Maestro's id selector.
appId: com.example.myapp
---
- launchApp
- tapOn:
id: "email"
- inputText: "user@example.com"
- tapOn: "Log in"
- assertVisible: "Welcome"maestro test .maestro/login.yamljest-expo preset in Expo) and React Native Testing Library.userEvent.
0 commentaire
Se connecter · Connectez-vous pour laisser un commentaire.
Soyez le premier à commenter.