Unit tests use JUnit 4 + Kotlin Coroutines test. Run with:
./gradlew test Key testing patterns:
// Coroutine rule
@get:Rule
val mainDispatcherRule = MainDispatcherRule()
// Test ViewModel
@Test
fun `load inbox returns threads`() = runTest {
val repo = mock<EmailRepository>()
whenever(repo.getInboxThreadsFlow(any())).thenReturn(flowOf(listOf(thread)))
val vm = InboxViewModel(repo, ..., settings)
advanceUntilIdle()
assertThat(vm.state.value).isInstanceOf(InboxState.Success::class.java)
assertEquals(1, (vm.state.value as InboxState.Success).threads.size)
} ./gradlew connectedGithubDebugAndroidTest | Tag | Area |
|---|---|
AuthManager | Auth flow, sign-in/out |
EmailRepository | Data layer operations |
InboxViewModel | Inbox state |
EmailDetailViewModel | Detail view state |
ActionQueueManager | Pending action processing |
RetrofitClient | HTTP request logging (debug builds only) |
# View logs for a specific tag
adb logcat -s InboxViewModel
# Check database contents
adb shell run-as com.shrivatsav.monomail
cd databases
# DB is encrypted — use Room's database inspector in Android Studio
# Check DataStore
adb shell run-as com.shrivatsav.monomail
cd shared_prefs The BuildConfig.DEBUG flag sets the start destination directly to Screen.SignIn (skipping the welcome screen) for faster iteration. There's also a Screen.SampleCompose route (debug only) for previewing the compose screen.
Production crashes are captured by CrashHandler and displayed in CrashActivity. The stack trace is saved to {cacheDir}/last_crash.txt.
Before submitting a PR:
./gradlew assembleGithubDebug builds./gradlew test passes