Skip to content

fix(e2e): capture logcat and screenshots when Android E2E fails - #466

Open
KisaneNeko wants to merge 2 commits into
callstack:mainfrom
KisaneNeko:ci/android-e2e-diagnostics
Open

KisaneNeko wants to merge 2 commits into
callstack:mainfrom
KisaneNeko:ci/android-e2e-diagnostics

Conversation

@KisaneNeko

@KisaneNeko KisaneNeko commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Why

While investigating the Expo 56 Android E2E failure in run 33749895553, I went looking for a screenshot or logcat to see what the app was doing. There weren't any. The upload step had quietly logged:

No files were found with the provided path: apps/AndroidApp/artifacts.
No artifacts will be uploaded.

The cause: detox-rc-androidapp-emulator-release.cjs has no artifacts section, so every plugin sits at Detox's all-off defaults (log: 'none', screenshot: 'manual'). Both iOS configs opt in via the shared getDetoxArtifactsConfig() helper — Android was the only one that never did. So no Android E2E failure has ever produced any evidence, on any flavour.

Why this makes the Expo 56 bug hard to debug

All we get from that run is the test's own message:

Timed out waiting for UIAutomator to contain any of: Hello native Android (Expo 56), ...

The app process had started. So the greeting either never rendered, or the app crashed, or it ANR'd, or the activity never reached the foreground — and there's no way to tell which, because nothing was recorded.

The timing makes that gap especially frustrating. In the Expo 57 job of the same run, the greeting appeared 3.9 seconds after the wait began. On Expo 56 it never appeared in 90 seconds. That's not a marginal timeout — it looks like a genuine app-side failure. But without logcat we can't say whether it was a crash, an ANR, or something else, so it's been written off as flakiness.

What changes

This just applies the existing iOS pattern to Android:

  • detox-rc-androidapp-emulator-release.cjs now does artifacts: getDetoxArtifactsConfig(), the same call both iOS configs already make. A failing test leaves a logcat and a beforeAllFailure.png.
  • That helper writes to e2e-artifacts/, so the upload path, if-no-files-found and retention-days now match appleapp-road-test, and .gitignore matches AppleApp and RNApp.

One deliberate deviation: video is disabled on Android. On iOS Detox records host-side via simctl io recordVideo (note the helper's iOS-only video.simulator.codec key). On Android it would be adb shell screenrecord writing into the emulator's userdata partition — the one this action already warns about: "Do not set disk-size — a large userdata partition fails when the runner is low on disk after Gradle/NDK builds." A unit test locks video off for Android and asserts the shared helper still has it on, so iOS can't regress.

No test behaviour changes — no timeouts, retries or waits touched. iOS is untouched.

Testing

Ran the Android Detox suite locally on Pixel_4_API_34 (same API level as CI), using the Expo 57 flavour since it shares this exact config factory:

  • Passing run: 2/2 green, e2e-artifacts/ correctly left empty (keepOnlyFailedTestsArtifacts).
  • Forced failure: produced beforeAllFailure.png, detox.log and logcat — about 1 MB, no video.

yarn test:apps 9/9, yarn lint clean. The action.yml change is validated by inspection and a YAML parse only; it has not been exercised by a CI run yet.

This does not fix the Expo 56 failure — root cause is still unknown. It makes the next occurrence diagnosable.

🤖 Generated with Claude Code

Android's Detox config had no `artifacts` section, so every plugin sat at
Detox's all-off defaults (log: 'none', screenshot: 'manual'). Both iOS configs
opt in via the shared getDetoxArtifactsConfig() helper; Android was the only
one that never did. The result: an Android E2E failure produced no logcat, no
screenshot and nothing to upload — see run 33749895553, where the upload step
logged "No files were found with the provided path: apps/AndroidApp/artifacts".

Reuse the shared helper, with video disabled. On iOS Detox records host-side
via `simctl io recordVideo` (note the helper's iOS-only video.simulator.codec
key); on Android it would be `adb shell screenrecord` writing into the emulator
userdata partition that this action already documents as ENOSPC-prone. A unit
test locks video off for Android and asserts the shared helper still has it on,
so iOS cannot regress.

The helper writes to e2e-artifacts/, so the upload path, if-no-files-found and
retention-days now match appleapp-road-test, and .gitignore matches AppleApp
and RNApp.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants