This episode covers testing and tooling: Jest with React Native Testing Library for unit tests, Detox for E2E, CI/CD with GitHub Actions, Fastlane and EAS Build for distribution, plus over-the-air updates with EAS Update.

The more features there are, the bigger the risk that one small change breaks another. Without tests, regressions are only detected when users complain in store reviews. Good testing is a safety net that makes a team brave enough to change code.
Episode 20 covers testing and tooling in React Native: Jest with React Native Testing Library for unit tests, Detox for end-to-end, CI/CD with GitHub Actions, Fastlane and EAS Build for distribution, plus over-the-air updates with EAS Update.
Jest is the default test runner for React Native projects. To test components, add React Native Testing Library:
npm install -D @testing-library/react-nativeComponent tests simulate user interactions and check the results:
import { render, fireEvent } from "@testing-library/react-native";
import { Counter } from "./Counter";
test("counter bertambah saat tombol ditekan", () => {
const { getByText } = render(<Counter />);
fireEvent.press(getByText("Tambah"));
expect(getByText("1")).toBeTruthy();
});fireEvent.press(getByText("Tambah")) simulates a button tap, then the assertion checks that the new number appears. This test runs without an emulator — fast enough to run on every commit.
Unit tests focus on logic and behavior: state changes correctly, handlers are called with the right arguments, and loading or error conditions appear as expected. Don't test implementation details like internal calls — test the behavior users can see.
Unit tests don't catch integration problems between screens or interactions with native libraries. Detox runs the real app on a simulator or emulator and automates user flows:
npm install -D detox
npx detox initdescribe("alur login", () => {
it("berhasil masuk dengan kredensial valid", async () => {
await device.reloadReactNative();
await element(by.id("email")).typeText("user@example.com");
await element(by.id("password")).typeText("rahasia");
await element(by.id("login-button")).tap();
await expect(element(by.id("beranda"))).toBeVisible();
});
});element(by.id("email")) selects an element via testID — add testID to components so the test is stable. Detox runs the whole app, so it needs an emulator and a matching build.
CI/CD runs tests and builds on every change without human intervention. An example GitHub Actions workflow:
name: ci
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm testThe workflow above installs dependencies and runs unit tests on every push to main. For Android, add a job that runs the Gradle build; for iOS, use a macOS runner.
Secrets like signing keys and access tokens are stored in GitHub Secrets, not in code. The pipeline reads secrets via environment variables and uses them during the build — consistent with the habits from episode 13.
Fastlane automates native app builds and distribution: managing signing, building, uploading to TestFlight and the Play Console:
cd ios
bundle exec fastlane betafastlane beta runs the lane configured in the Fastfile — fetching signing profiles, building, and uploading the build.
For Expo projects, EAS Build runs native builds in the cloud with per-environment profiles:
npx eas build --profile production --platform androidnpx eas build --profile production builds a production APK or AAB on the EAS servers without local native setup.
Small changes like UI bug fixes don't need to wait for store review. EAS Update sends the JavaScript bundle directly to devices:
npx eas update --channel production --message "perbaikan logout"This update only applies to JavaScript code — native changes still require a store build. Rule of thumb: JS fixes via OTA, native changes via build.
Warning
OTA updates aren't a replacement for testing. Code downloaded by devices runs in production, so apply a process just as strict as a store release — automated tests, staging, and a clear rollback.
Episode 20 completed the quality chain: Jest and RNTL for unit tests, Detox for E2E, CI/CD with GitHub Actions, Fastlane and EAS Build for distribution, and EAS Update for over-the-air fixes.
Key takeaways:
In the next episode, episode 21, we'll discuss modern features and the roadmap: the React Native 0.86 release and its cycle, the direction of the New Architecture and React 19, accessibility improvements, and the position of the Expo SDK and reactnative.directory in the ecosystem.