test: add end-to-end smoke tests covering every demo activity - #1007
Conversation
Coverage (unit tests)No unit baseline recorded in
Line and branch coverage from unit test reports. History is recorded in |
dd2684b to
5f8d892
Compare
|
Added three commits:
Locally on an API 34 emulator with a real key: |
Reviewing a pull request currently means cloning it and clicking through the sample app by hand to confirm nothing regressed. These two tests do that walk automatically. DemoAppSmokeTest is parameterized over allActivityGroups, the same registry that builds the on-screen demo list, so a demo added to the app is covered with no change to the test. Each demo is launched and checked for three things: it reaches RESUMED, a MapView or StreetViewPanoramaView is attached and laid out, and nothing crashes on a background thread. It then recreates the activity and checks again, which is where camera and marker state holders tend to regress. DemoRegistryTest guards the registry itself. A demo is described both in allActivityGroups and in AndroidManifest.xml; adding it to one and not the other builds cleanly and only fails when someone taps the entry. Map content is deliberately not asserted. Verifying that a particular marker or overlay is drawn belongs in the focused tests alongside these; the value here is breadth.
Emulators never update Google Play services. The bundled version on older images crashes inside Play services when adding advanced markers. When the Maps API key secret is available, the demo smoke test also waits for map tiles to render. (cherry picked from commit 22d2871)
… test Zooming out and back in exercises the camera listeners the demos and the library hook into. With requireMapLoaded=true, which CI passes when the Maps API key secret is available, the test also waits for tiles to render.
On macOS-latest-large the API 36 emulator took over five minutes to boot and the job hit its 30 minute timeout. Ubuntu runners support KVM and boot it in about a minute. Raise the timeout to 45 minutes for headroom.
dafa07a to
12db67e
Compare
DemoMenuNavigationTest starts MainActivity, taps the demo's group and entry, waits for its map, and presses back to the menu, so a broken menu entry, click handler or back navigation is caught. DemoRegistryTest now also fails when a demo activity is declared in the manifest but missing from the menu. Adds test tags to the menu cards.
|
Added the menu flow:
Locally on an API 34 emulator: |
Code Coverage
|
Move DemoAppSmokeTest, DemoMenuNavigationTest and DemoRegistryTest into a smoke package. A new Demo smoke test workflow runs only that package on API 36 with KVM and a real key, and the instrumentation workflow excludes it and goes back to its previous runner, API level and timeout, so the coverage history stays comparable. DemoAppSmokeTest now zooms a map that is fully on screen, which fixes a flaky wait in MapsInLazyColumnActivity.
|
Split the smoke tests from the regular instrumentation tests:
Locally: |
dkhawk
left a comment
There was a problem hiding this comment.
LGTM with a few minor observations and suggestions:
assumeValidApiKeyinDemoMenuNavigationTest: The PR description notes that both suites skip when an API key is not present viaassumeTrue(hasValidApiKey).DemoAppSmokeTesthas this, butDemoMenuNavigationTestappears to be missing the@Beforecheck (orassumeValidApiKey()). Adding it will prevent unexpected timeouts if someone runs the smoke suite locally without a key insecrets.properties.- Defensive scroll on group headers: In
DemoMenuNavigationTest, adding.performScrollTo()before.performClick()ongroupTestTag(group)would protect against smaller screens or landscape orientation where lower groups might be below the fold. - StreetView coverage in navigation: In
DemoMenuNavigationTest,DEMOS_WITHOUT_MAPexemptsStreetViewActivitybecausefindMapViewonly looks forMapView. SinceStreetViewPanoramaViewsupportsgetStreetViewPanoramaAsync, supporting both (likeDemoAppSmokeTestdoes withmapSurfaces) would eliminate the exemption. - Background crash detection:
DemoAppSmokeTest's uncaught exception handler is great. Consider applying the same check toDemoMenuNavigationTest, and also checkingassertNoUncaughtExceptions()in@After tearDown()to catch any crashes during activity teardown.
Overall, the design is excellent—generating the test matrices directly from allActivityGroups and keeping the manifest in sync via DemoRegistryTest makes this completely maintenance-free.
- DemoMenuNavigationTest scrolls the menu to each group and demo before clicking, since items below the fold are not composed until the LazyColumn scrolls to them. - It covers StreetViewActivity through its StreetViewPanoramaView instead of exempting it. The wait advances the compose test clock, which drives every composition in the process: the panorama only appears after a recomposition that follows an async metadata request. Without a valid key, that demo is only checked for opening. - Both tests record background-thread crashes and check for them in @after as well, to catch crashes during teardown. tearDown only restores the default handler it replaced.
|
Thanks @dkhawk! Pushed c189955 with these:
Locally with a real key: 71/71 (44 + 22 + 5). |
|
Correction on point 1: I mixed up the report with the build result. As #1016 notes, AGP records skipped assumptions as |
Problem
Following up on a pull request currently means cloning it, building it, and clicking through every screen of the sample app to confirm nothing regressed. That is slow, easy to skip, and the coverage varies with whoever is reviewing.
What this adds
Two instrumentation tests in
maps-app, both driven offallActivityGroupsinDemo.kt, the single registry that already builds the on-screen demo list. A demo added to the app is covered automatically, with no change to either test. That is the property that makes this worth having rather than another list to keep in sync.DemoAppSmokeTestParameterized over all 22 demos, two checks each:
demoLaunchesAndShowsMap: the activity reachesRESUMED, aMapVieworStreetViewPanoramaViewis attached, visible and non-zero sized, and nothing crashed on a background thread. The map surface is polled rather than checked once, becauseAndroidViewlays it out a frame or more after the activity resumes.demoSurvivesConfigurationChange: the same checks, thenrecreate(), then the same checks again. Configuration changes are where camera and marker state holders tend to regress and are tedious to verify by hand.Map content is deliberately not asserted. Whether a particular marker or overlay is drawn belongs in the focused tests alongside this one; the value here is breadth.
DemoRegistryTestGuards the registry itself. A demo is described in two places that have to agree:
allActivityGroupsandAndroidManifest.xml. Adding it to one and not the other compiles, builds, and only fails when someone taps the entry. Four checks: every demo resolves viaPackageManager, is enabled, has non-blank title and description strings, and is not registered twice.Verification
Run against a Pixel 8 emulator (API 36) with a valid Maps API key:
DemoAppSmokeTestDemoRegistryTest:maps-app:lintDebugAll 22 demos launch, show a map surface, and survive recreation today, so no demo needed an exemption and
DEMOS_WITHOUT_MAP_SURFACEis empty.Cost
DemoAppSmokeTestadds about 2.5 minutes to the emulator job, which currently runs 16 to 28 minutes. If that proves too much for the pull request gate,demoSurvivesConfigurationChangeis the half to move to a nightly run: it roughly doubles the class's runtime and catches the rarer class of bug.Notes
Both tests skip rather than fail when no Maps API key is configured, via
assumeTrue(hasValidApiKey), matching how forks run CI without access to the secret. Worth knowing when reading a green run from a fork: the emulator job injects the key, so skipping only happens where the secret is genuinely unavailable.