You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: okf-bundle/ci-workflows/android.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@
6
6
2.`yarn tests:android:post-e2e-coverage` — poll/pull `coverage.ec`, Jacoco report (best-effort, never fails the job)
7
7
3. Codecov upload — `continue-on-error: true`
8
8
9
-
Native Android coverage is **not** pulled inside `tests/e2e/firebase.test.js`. Pulling mid-Detox ran before `DetoxTest.dumpCoverageData()`and routinely missed the file.
9
+
Native Android coverage is **not** pulled inside `tests/e2e/firebase.test.js`. The Jet `after` hook in `tests/app.js` calls `RNFBTestingCoverage.flush()`in the **app process** to write `coverage.ec` before Detox SIGINTs instrumentation. Post-e2e pull runs after Detox exits.
10
10
11
11
## CI failure: Jet 1006 → adb `reverse --remove` mid-run
12
12
@@ -40,7 +40,7 @@ When the Jet/app WebSocket drops (1006), Detox can treat the session as dead and
40
40
41
41
| Symptom | Likely cause |
42
42
|---------|----------------|
43
-
|`[native-coverage] Android native coverage pull failed`|Detox exited before instrumentation wrote `coverage.ec`; post-e2e poll may still recover it|
43
+
|`[native-coverage] Android native coverage file not found after N attempts`|App-process flush did not run or failed; check Jet log for `[native-coverage] flushing android coverage`|
44
44
| Empty Jacoco XML (~235 bytes) | No `.ec` pulled — check post-e2e logs |
45
45
|`adb reverse --remove` in Detox logs | Expected on 1006; should be warn-only after Detox patch |
46
46
| Detox red, tests green in log | Pre-patch: teardown adb error; re-run or check patch applied |
Copy file name to clipboardExpand all lines: okf-bundle/testing/coverage-design.md
+27-18Lines changed: 27 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,17 +33,18 @@ flowchart LR
33
33
N --> T2[coverage/lcov.info]
34
34
end
35
35
subgraph android_native [E2e Android native]
36
-
D1[Detox e2e] --> EC[coverage.ec in app]
36
+
D1[Detox e2e] --> FLA[RNFBTestingCoverage.flush]
37
+
FLA --> EC[coverage.ec in app filesDir]
37
38
EC --> P1[pull-native-coverage.js]
38
39
P1 --> J1R[jacocoAndroidTestReport]
39
40
J1R --> AX[jacoco XML]
40
41
end
41
42
subgraph ios_native [E2e iOS native]
42
-
D2[Detox e2e] --> FL[RNFBTestingCoverage.flush]
43
-
FL --> PR[coverage.profraw in Documents]
43
+
D2[Detox e2e] --> FLI[RNFBTestingCoverage.flush]
44
+
FLI --> PR[coverage.profraw in Documents]
44
45
PR --> P2[pull-native-coverage.js]
45
46
P2 --> LLVM[process-ios-native-coverage.js]
46
-
LLVM --> I2[coverage/ios-native.lcov.info]
47
+
LLVM --> I2[coverage/ios-native/lcov.info]
47
48
end
48
49
J2 --> C[Codecov]
49
50
T2 --> C
@@ -108,14 +109,18 @@ After a Detox/macOS e2e run, expect log lines like `[jet-coverage] WS received N
108
109
## Pipeline
109
110
110
111
1. Gradle enables `testCoverageEnabled` on RNFB Android library modules (`tests/android/build.gradle`).
111
-
2. Detox e2e runs; the instrumented app writes `coverage.ec` when instrumentation finishes (`DetoxTest.dumpCoverageData()` after `Detox.runTests()`returns).
112
+
2. Detox e2e runs Jet tests in the instrumented app. After all Mocha tests complete, the Jet `after` hook in `tests/app.js` calls `NativeModules.RNFBTestingCoverage.flush()`(`RNFBTestingCoverageModule` in the **app** process). This writes `coverage.ec` to the app `filesDir`**before** Detox SIGINTs the instrumentation process.
112
113
3.**After Detox exits**, `yarn tests:android:post-e2e-coverage` (CI) or `yarn tests:android:pull-native-coverage` polls for `coverage.ec`, pulls it to `tests/android/app/build/output/coverage/emulator_coverage.ec`, then runs `jacocoAndroidTestReport`. A missing file logs a warning and does **not** fail the Detox test or the CI job (`continue-on-error` on Codecov upload).
CI runs step 3 inside the emulator job immediately after `yarn tests:android:test-cover`.
118
119
120
+
## Why flush runs in the app process
121
+
122
+
Detox sends **SIGINT** to the instrumentation process as soon as the Jet session ends. A Jacoco dump placed after `Detox.runTests()` in `DetoxTest.java` never runs. The app-process native module mirrors the iOS LLVM flush pattern: JS test completion → native module → file on disk → post-e2e pull.
123
+
119
124
## Jacoco configuration notes
120
125
121
126
- Class directories must use the AGP 8.x path: `build/intermediates/javac/debug/compileDebugJavaWithJavac/classes` (not legacy `.../debug/classes`).
@@ -141,7 +146,7 @@ CI runs step 3 inside the emulator job immediately after `yarn tests:android:tes
141
146
- merges `.profraw` from `tests/ios/build/output/coverage/` (Detox) and optionally `Build/ProfileData/` (`xcodebuild test` only — not used by Detox today)
142
147
- exports lcov with `xcrun llvm-cov export -format=lcov` against the main app binary (statically linked RNFB code), writing to a temp file (large reports exceed Node stdout buffer limits)
143
148
- streams and rewrites `SF:` paths to repo-relative `packages/**` paths
144
-
- writes **`coverage/ios-native.lcov.info`**
149
+
- writes **`coverage/ios-native/lcov.info`**
145
150
-**deletes the processed `.profraw` files** so a missing file on the next run is a clear signal that e2e did not produce fresh native coverage
146
151
147
152
## Objective-C and Swift
@@ -156,20 +161,20 @@ The Podfile `post_install` coverage flags are temporary. When native dependencie
156
161
157
162
# Codecov uploads (CI)
158
163
159
-
CI uses [codecov-action](https://github.com/codecov/codecov-action)v6 with `verbose: true`. It discovers coverage files under the repo, including:
164
+
CI uses [codecov-action](https://github.com/codecov/codecov-action)v7 with `verbose: true`. It auto-discovers coverage files under the repo, including:
The iOS workflow runs `yarn tests:ios:test:process-coverage` after Detox (`if: always()`, `continue-on-error: true` for now). The process step exits 1 when profraw is missing.
169
174
170
175
## File naming
171
176
172
-
The repo standard for JavaScript lcov is `coverage/lcov.info`. iOS native uses **`coverage/ios-native.lcov.info`**. Codecov detects **lcov format by file content**, not only by the exact name `lcov.info`.
177
+
The repo standard for JavaScript lcov is **`coverage/lcov.info`**. iOS native lcov is **`coverage/ios-native/lcov.info`** — the basename `lcov.info` is required for codecov-action auto-discovery (files like `ios-native.lcov.info` are not matched). Android native coverage is **Jacoco XML**, not lcov; codecov discovers `jacoco*.xml` once the report is generated.
173
178
174
179
Check the Codecov commit **Uploads** tab for **Processed** vs **Unusable** per upload — that is the authoritative signal, not small project percentage deltas.
Metro must be running (`yarn tests:packager:jet`) for Detox e2e.
199
204
200
205
# Critical invariants
201
206
202
-
These must all be true for native iOS coverage to work. If any break, the e2e test should fail (not silently upload stale data).
207
+
These must all be true for native coverage to work. If any break, the e2e test should fail (not silently upload stale data).
203
208
204
209
| Invariant | Where enforced |
205
210
|-----------|----------------|
206
-
| App built with LLVM profile flags |`Podfile``post_install` (run `pod install`) |
207
-
| Profile path set at launch |`AppDelegate` → `RNFBTestingConfigureCoverageProfilePath()`|
208
-
| JS module name matches native export |`RCT_EXPORT_MODULE(RNFBTestingCoverage)` + `NativeModules.RNFBTestingCoverage` in `tests/app.js`|
209
-
| Flush runs after Mocha tests | Jet `after` hook in `tests/app.js`|
210
-
| Profraw pulled before Detox teardown |`pull-native-coverage.js` on Jet `close` in `firebase.test.js` (iOS only) |
211
+
| App built with LLVM profile flags (iOS) |`Podfile``post_install` (run `pod install`) |
212
+
| Profile path set at launch (iOS) |`AppDelegate` → `RNFBTestingConfigureCoverageProfilePath()`|
213
+
| App built with Jacoco instrumentation (Android) |`testCoverageEnabled` in `tests/android/build.gradle`|
214
+
| JS module name matches native export |`RNFBTestingCoverage` on iOS + Android; `NativeModules.RNFBTestingCoverage` in `tests/app.js`|
215
+
| Native flush runs after Mocha tests | Jet `after` hook in `tests/app.js` (iOS + Android) |
216
+
| Profraw pulled before Detox teardown (iOS) |`pull-native-coverage.js` on Jet `close` in `firebase.test.js`|
211
217
| Android `coverage.ec` pulled after Detox |`yarn tests:android:post-e2e-coverage` in CI / local post-e2e step |
212
-
| Fresh profraw processed after e2e |`process-ios-native-coverage.js` (deletes profraw after export) |
218
+
| Fresh profraw processed after e2e (iOS) |`process-ios-native-coverage.js` (deletes profraw after export) |
213
219
214
220
# Troubleshooting
215
221
@@ -219,10 +225,13 @@ These must all be true for native iOS coverage to work. If any break, the e2e te
219
225
| No profraw after e2e; test still passes (old behaviour) | Pull in `afterAll` after `detox.cleanup()`, or wrong module name | Pull on Jet `close`; verify `RNFBTestingCoverage` export name |
220
226
| Stale profraw uploaded | Re-processed old file without re-running e2e | Process step deletes profraw after export; missing file + exit 1 on next process |
221
227
|`process-ios-native-coverage` succeeds but no `packages/` hits | Wrong binary / not instrumented | Rebuild with `yarn tests:ios:build`; check Podfile flags |
222
-
| Empty Jacoco XML (~235 bytes) | AGP 8 class path, missing `src/reactnative/java`, or no `coverage.ec` pulled | See `jacocoAndroidTestReport`; check `[native-coverage] Android native coverage pull failed` warning |
228
+
| Empty Jacoco XML (~235 bytes) | AGP 8 class path, missing `src/reactnative/java`, or no `coverage.ec` pulled | See `jacocoAndroidTestReport`; check post-e2e poll logs |
229
+
| Android `coverage.ec` missing after passing e2e | Detox SIGINT before instrumentation `@Test` tail; flush not called from app | Verify `[native-coverage] flushing android coverage` in Jet log; check `RNFBTestingCoverageModule` registered in `MainApplication`|
230
+
| Jet `after` hook logs coverage not enabled | Non-instrumented build (local release or no Jacoco/LLVM flags) | Expected on `tests:android:test` without debug Jacoco; use debug e2e builds for native coverage; hook catches errors so tests still pass |
223
231
| iOS link: `swiftCompatibility56` undefined | Profile link flags applied to all Pods | Restrict `OTHER_LDFLAGS` profile flags to app target; RNFB pods compile-only |
224
232
| No `[jet-coverage] WS received` lines | Patches not applied |`yarn install` from repo root; check `.yarn/patches/`|
225
233
| NYC summary missing / empty `lcov.info`| Jet not run from `tests/` cwd | Detox spawns `yarn jet` inside `tests/`; macOS uses `cd tests && npx jet`|
234
+
| Codecov missing iOS native files | Output not named `lcov.info`| Use `coverage/ios-native/lcov.info` (not `coverage/ios-native.lcov.info`) |
0 commit comments