P8: Roborazzi golden image pipeline live
Records initial golden set + wires verifyRoborazziDebug into CI. Diffs
uploaded as artifact on failure. ScreenshotTests @Ignore removed.
Root cause of the prior RoboMonitoringInstrumentation:102 failure:
createComposeRule() launches ActivityScenarioRule<ComponentActivity>
which fires a MAIN/LAUNCHER intent, but the merged unit-test manifest
declares androidx.activity.ComponentActivity without a LAUNCHER filter,
so Robolectric's PM returns "Unable to resolve activity for Intent".
Fix: switch to the standalone captureRoboImage(path) { composable }
helper from roborazzi-compose, which registers
RoborazziTransparentActivity with Robolectric's shadow PackageManager
at runtime and bypasses ActivityScenario entirely.
Also pin roborazzi outputDir to src/androidUnitTest/roborazzi so
goldens live in git (not build/) and survive gradle clean.
36 goldens, 540KB total.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,19 +50,27 @@ consume every colour slot the real screens use.
|
||||
./gradlew :composeApp:compareRoborazziDebug
|
||||
```
|
||||
|
||||
Output lands under `composeApp/build/outputs/roborazzi/`.
|
||||
Committed goldens live at
|
||||
`composeApp/src/androidUnitTest/roborazzi/` — pinned there via the
|
||||
`roborazzi { outputDir = ... }` block in `composeApp/build.gradle.kts`
|
||||
so they survive `gradle clean`. Diffs and intermediate artefacts land
|
||||
under `composeApp/build/outputs/roborazzi/` and are uploaded as a CI
|
||||
artifact on failure (`android-ui-tests.yml → Upload screenshot diffs
|
||||
on failure`).
|
||||
|
||||
## Golden-image workflow
|
||||
|
||||
Roborazzi goldens are *not* auto-committed. The workflow is:
|
||||
Roborazzi goldens *are* committed alongside the tests — see
|
||||
`composeApp/src/androidUnitTest/roborazzi/`. The workflow is:
|
||||
|
||||
1. Developer changes a composable (intentionally or otherwise).
|
||||
2. CI runs `verifyRoborazziDebug` and fails on any drift.
|
||||
2. CI runs `verifyRoborazziDebug` and fails on any drift; the
|
||||
`roborazzi-diffs` artifact is uploaded for review.
|
||||
3. Developer inspects the diff locally via `compareRoborazziDebug` or
|
||||
from the CI artifact.
|
||||
4. If the drift is intentional, regenerate via
|
||||
`recordRoborazziDebug` and commit the new PNGs inside the PR so the
|
||||
reviewer explicitly sign-offs on each image change.
|
||||
reviewer explicitly signs off on each image change.
|
||||
5. If the drift is a regression, fix the composable and re-run.
|
||||
|
||||
**Reviewer checklist:** every committed `.png` under the roborazzi output
|
||||
@@ -94,6 +102,16 @@ Add the corresponding dark-mode and other-theme variants, then run
|
||||
- `captureRoboImage` only captures the composable tree, not window
|
||||
chrome (status bar, navigation bar). That's intentional — chrome
|
||||
is owned by the OS, not our design system.
|
||||
- We use the standalone `captureRoboImage(filePath) { composable }`
|
||||
helper from `roborazzi-compose` instead of the
|
||||
`createComposeRule() + RoborazziRule` approach. The helper registers
|
||||
`RoborazziTransparentActivity` with Robolectric's shadow PackageManager
|
||||
on its own, avoiding the
|
||||
"Unable to resolve activity for Intent MAIN/LAUNCHER cmp=.../ComponentActivity"
|
||||
failure you hit if `createComposeRule` tries to launch
|
||||
`androidx.activity.ComponentActivity` through `ActivityScenario` on the
|
||||
unit-test classpath (where the manifest declares `ComponentActivity`
|
||||
without a MAIN/LAUNCHER intent filter).
|
||||
|
||||
## References
|
||||
|
||||
|
||||
Reference in New Issue
Block a user