Add instrumented smoke tests with Gradle Managed Devices#219
Closed
Add instrumented smoke tests with Gradle Managed Devices#219
Conversation
Gradle Managed Device (Pixel 6, API 34, ATD image) for hermetic test execution. Espresso, Compose test, and test orchestrator deps. Animations disabled for determinism.
Always grants audio focus. No system interaction.
Implements Playback interface with immediate success callbacks. No real audio — just state tracking for UI verification.
Extract PlaybackEngineModule (ExoPlayer, AudioFocus, PlaybackManager) and CastModule (Cast service bindings) from PlaybackModule. Extract DatabaseModule from RepositoryModule. Change PlaybackManager constructor to accept Playback interface instead of concrete ExoPlayerPlayback. No behavioral changes — purely structural split.
TestPlaybackEngineModule: FakePlayback + FakeAudioFocusHelper TestCastModule: empty (suppresses cast dependencies) TestDatabaseModule: in-memory Room database
Replaces AppModuleBinds with empty initializer set to avoid pulling in Cast, Billing, Firebase, etc. during smoke tests.
10 songs across 3 artists and 6 albums. Seeds Room DB and sets hasOnboarded preference to skip onboarding flow.
4 tests covering critical paths: - App launch + library visible - Library tabs show seeded songs - Tap song activates mini player - Search screen accessible
4 new tests covering: - Artist list → artist detail navigation - Mini player → full now playing expansion - Queue shows items after playing - Home screen buttons visible
- artistDrillDown: scope toolbar check to CollapsingToolbarLayout and remove redundant recyclerView assertion (multiple coordinatorLayouts) - tapSong_expandNowPlaying: scope playPauseButton and seekBar to sheet1Container, add isClickable to disambiguate PlayStateView from its child PlayPauseAnimationView
4 new tests covering: - Shuffle all from home starts playback - Search with typed query shows results - Playlists tab loads without crashing - Settings bottom sheet opens
Single test that visits all major app destinations: Home, Library (all 5 tabs), Search, Settings, Artist/Album/Genre detail screens, Now Playing, and Queue.
Polling-based waitForView utility returns immediately when the view condition is met instead of always waiting a fixed duration. Better failure messages on timeout. Removes unnecessary animation sleeps (animations already disabled in testOptions).
…rView Navigation tests (3 tests): - bottomNavAndTabs: visits Home, Library, Search, Settings + all 5 tabs - detailScreens: artist detail and album detail navigation - playbackScreens: mini player and now playing expansion Medium-value tests (4 tests): - shuffleAll_startsPlayback - search_typingQuery_showsResults - playlistsTab_isAccessible - settings_isAccessible Replaced all Thread.sleep with polling waitForView utility that returns immediately when condition is met. Fixed ViewPager2 ambiguous RecyclerView matches. Fixed album grid shuffle header at position 0.
QueueFragment.onSlide accessed auto-cleared toolbarTitleTextView after onDestroyView. BottomSheetBehavior's settling animation posts onSlide callbacks via Choreographer, which can fire after the fragment's view is destroyed. Fix: change toolbarTitleTextView, toolbarSubtitleTextView, emptyLabel, and progressBar from autoCleared to autoClearedNullable with safe calls. Re-enable queue navigation in smoke test.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
waitForViewpolling utility replaces allThread.sleep— tests return immediately when conditions are metPlaybackModuleintoPlaybackModule+PlaybackEngineModule+CastModulefor surgical test DI replacementFakePlayback+FakeAudioFocusHelperat the hardware boundary — everything else (QueueManager, repositories, PlaybackManager) runs realQueueFragmentcrash on sheet slide after view destroy (auto-cleared value accessed inonSlidecallback afteronDestroyView)Test plan
./gradlew :android:app:pixel6Api34AtdDebugAndroidTest— 16/16 pass./gradlew :android:app:assembleDebug— production build unaffected