Skip to content

test+ci(app): JVM render tests for the app shell + Lint in CI - #12

Open
NiDrZero wants to merge 2 commits into
mainfrom
phase3-shell-verify
Open

test+ci(app): JVM render tests for the app shell + Lint in CI#12
NiDrZero wants to merge 2 commits into
mainfrom
phase3-shell-verify

Conversation

@NiDrZero

@NiDrZero NiDrZero commented Aug 14, 2026

Copy link
Copy Markdown
Owner

What this PR does (plain English)

Two related "verify the app shell" improvements:

  1. Render tests — the honest substitute for the device-launch check.
  2. Lint in CI — so the static-analysis pass runs automatically forever, not
    just once locally.

1. Render tests

Until now the app shell (PR #10) was only ever proven to compile. Compiling
doesn't prove the screens actually draw — a screen can compile fine and still
crash the moment Compose lays it out (bad theme, missing resource, an icon that
won't resolve). A real emulator can't run in this environment (no hardware
virtualization), so these tests use Robolectric, which gives a genuine
Android runtime on the plain JVM. The Compose test rule actually composes and
lays out each screen, then asserts its content is present.

Tested:

  • Home renders by default — full shell (Scaffold + bottom nav + Material 3
    theme + HomeScreen runtime-status card).
  • Terminal tab — tapping it swaps to the placeholder screen (nav works).
  • Settings tab — tapping it renders the read-only config rows.

2. Lint in CI

Adds a :app:lintDebug step to .github/workflows/ci.yml so lint runs on every
push and PR to main. Lint fails the build on errors only (its default);
existing by-design warnings (arm64-only ABI, no launcher icon yet, minor
test-dep bumps) are reported but don't fail CI. Repo has 0 lint errors today,
so the gate is green now and will catch any NEW error later. The lint report is
uploaded as an artifact, mirroring the existing test-report upload.

Changes

  • gradle/libs.versions.toml — add robolectric 4.16 (supports API 23–36 / AGP
    8.12 per the compatibility table)
    and androidx-test-core 1.6.1; add compose-ui-test-junit4 / ui-test-manifest
    (versioned by the existing Compose BOM).
  • app/build.gradle.kts — enable testOptions.unitTests.isIncludeAndroidResources;
    add the test deps + Compose BOM to the test classpath.
  • AtomuxAppRenderTest.kt — the three render tests.
  • .github/workflows/ci.yml — the lint step + lint-report artifact upload.

Verification (run locally on this branch, exact CI commands)

  • ./gradlew :app:testDebugUnitTest --rerun-tasksBUILD SUCCESSFUL, 3
    tests, 0 skipped, 0 failures.
  • ./gradlew :app:lintDebug --no-daemon --stacktraceBUILD SUCCESSFUL, 0
    errors (7 pre-existing/by-design warnings).

Honest limitation

Render tests prove the screens draw and navigate on a JVM Android runtime — not
a substitute for a real screen (fonts, device dynamic-color, true pixel layout).
That one-time human eyeball check is still worth doing on a device eventually.

Not merging

Left open for your review.

Adds Robolectric-backed Compose UI render tests that actually compose and lay
out each screen of the Atomux app shell on the plain JVM (no emulator/device),
then assert their content renders. This is the honest substitute for a device
launch check, closing the gap where the shell was previously only proven to
compile, never to render.

- gradle/libs.versions.toml: add robolectric 4.16 (supports API 23-36 / AGP
  8.12 per the Robolectric compatibility table, matching this repo) and
  androidx-test-core 1.6.1; add compose-ui-test-junit4 / ui-test-manifest
  (versioned by the existing Compose BOM).
- app/build.gradle.kts: enable testOptions.unitTests.isIncludeAndroidResources
  (required for Robolectric to load the Material 3 theme + manifest on the JVM);
  add the test dependencies and the Compose BOM to the test classpath.
- AtomuxAppRenderTest: renders the full shell in an empty ComponentActivity via
  createAndroidComposeRule, then (1) asserts Home + runtime-status card + the
  three nav destinations render by default, (2) taps Terminal and asserts the
  placeholder screen renders, (3) taps Settings and asserts real config rows
  render. Runs on the JVM in normal CI; no hardware acceleration needed.

Verified locally: ./gradlew :app:testDebugUnitTest -> BUILD SUCCESSFUL, all 3
render tests pass (0 skipped, 0 failed). ./gradlew :app:lintDebug -> BUILD
SUCCESSFUL, 0 errors (7 pre-existing/by-design warnings, none from this change).
Adds a :app:lintDebug step to CI so the static-analysis pass runs on every push
and PR to main, not just as a one-time local check. Lint catches resource,
manifest, and layout/accessibility issues that the compiler and unit tests do
not.

Behavior: Lint fails the build on lint *errors* only (its default); existing
by-design warnings (arm64-only ABI, no launcher icon yet, minor test-dep bumps)
are reported but do not fail CI. The repo currently has 0 lint errors, so the
gate is green today and will flag any NEW error a future change introduces. The
HTML/XML lint report is uploaded as an artifact (always()), matching the
existing unit-test report upload.

Verified locally with the exact CI command: ./gradlew :app:lintDebug
--no-daemon --stacktrace -> BUILD SUCCESSFUL (0 errors).
@NiDrZero NiDrZero changed the title test(app): JVM render tests for the Compose app shell (device-launch substitute) test+ci(app): JVM render tests for the app shell + Lint in CI Aug 14, 2026
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.

1 participant