JavaScript coverage tools only see the JavaScript bundle. The Objective-C++, Swift, and Kotlin in your TurboModules run on the device during end-to-end tests, but no report records them. Unit tests mock those modules, so they do not record them either. A passing build can therefore ship a native change with no evidence that the change ran, including a change a coding agent wrote.
Important: Add this package only to a dedicated test app, never to the app you ship. Listing it as a
devDependencydoes not keep it out, because autolinking still includes the native module. That test app must run React Native's New Architecture.
Prompt your agent:
Read https://docs.page/invertase/react-native-coverage/app-developers.md, and set up react-native-coverage in this project.Or set it up yourself in three steps.
yarn add react-native-coverage
# or: npm install react-native-coverageFollow the path that matches the test app.
If the test app uses Expo: add the config plugin to its app.json file, then generate the native projects.
{
"expo": {
"plugins": [
[
"react-native-coverage",
{
"libraryProjectMatchers": ["my-native-lib"],
"frameworkNamePrefixes": ["MyLib"],
"enableAndroidCoverage": true,
"forceDynamicFrameworks": false
}
]
]
}
}npx expo prebuildIf the test app does not use Expo: apply the shipped android/rn-coverage*.gradle helpers and the cocoapods/coverage_post_install.rb helper. Use the Android and iOS pages for where each file goes. Copy react-native-coverage.config.js.example if your paths differ from the defaults.
After your tests, call Coverage.flush() once, then build the reports:
# Android
rn-coverage android pull && rn-coverage android report
# iOS
rn-coverage ios pull && rn-coverage ios export && rn-coverage ios report
rn-coverage assertrn-coverage assert exits 2 when a report is missing or empty, which fails the job.
Use the App developers guide for both setups in full, and the CLI page for every other command.
Build the test app with coverage turned on, using the Expo config plugin or the Gradle and CocoaPods helpers. When the tests finish, call Coverage.flush() to write coverage out of the running app. Then use rn-coverage to build the reports and fail the job when a report is empty.
| Feature | What it does |
|---|---|
| Expo config plugin, or the Gradle and CocoaPods helpers | Turns native coverage on when the test app is built |
| TurboModule | flush() writes the iOS LLVM counters and the Android Emma dump, plus Istanbul global.__coverage__ when that data is present |
CLI (rn-coverage) |
pull and report build the LCOV and JaCoCo files. assert exits 2 when those files are missing or empty |
| JavaScript and TypeScript coverage | babel-plugin-istanbul and NYC map the instrumented bundle back to the TypeScript you edit |
This repository runs the same setup on every pull request, with its example apps on an iOS Simulator and an Android emulator under Appium. Find the reports on Codecov.
Each flag is one run of the example apps:
| Flag | Example app | What ran | Coverage |
|---|---|---|---|
e2e-ios-dynamic |
example-dynamic/ |
iOS native, dynamic frameworks | 90.6% |
e2e-ios-static |
example/ |
iOS native, static libraries | 63.1% |
e2e-android |
example/ |
Android native (Emma to JaCoCo) | 81.7% |
unit-js |
This repository | Jest unit tests, JavaScript and TypeScript | 52.6% |
The package also measures its own native code. Its iOS source file, ios/Coverage.mm, has 71.88% line coverage. The screenshot shows which of its lines ran. Use the Contributing guide to run the example apps locally.
- Coverage — what it measures and how the pipeline works
- Install guides for app developers, library maintainers, and coding agents
- CLI and Configuration
- Empty or missing coverage
- Questions: Discord
- Bugs & feature requests: Open an issue
- Pull requests
- Contributing guide
- Releasing
- Code of Conduct
Apache-2.0 — see LICENSE.
Built and maintained by Invertase.
