Skip to content

chore: Improve Unit Test and Instrumentation Test Coverage#514

Open
adeekshith wants to merge 11 commits intomainfrom
feat/test-coverage
Open

chore: Improve Unit Test and Instrumentation Test Coverage#514
adeekshith wants to merge 11 commits intomainfrom
feat/test-coverage

Conversation

@adeekshith
Copy link
Owner

No description provided.

- Add Robolectric unit tests for PreferencesManager (80 tests), CustomRepliesData
  (17 tests), NotificationUtils (12 tests), and Constants (20 tests)
- Add instrumentation tests for MainActivity and PreferencesManager on real device
- Add mockito-kotlin dependency for Kotlin-idiomatic mocking
- Add @VisibleForTesting resetInstance() methods to PreferencesManager and
  CustomRepliesData for test isolation
- Guard EncryptedSharedPreferences init against hardware Keystore unavailability
  in test environments by catching Error in addition to checked exceptions
- Guard string resource lookups in init() with try-catch to handle Robolectric
  resource resolution limitations; pre-initialize keys with literal fallback values
Tests added (202 total, 0 failures):
- NetworkModelsTest: 35 tests covering all OpenAI/Atomatic request+response POJOs
  including AtomaticAIErrorResponse.isAuthError() branch logic
- MessageLogTest: 17 tests covering Room entity constructor, getters/setters, UUID generation
- GithubReleaseNotesTest: 9 tests covering Parcelable serialization via writeToParcel/CREATOR
- NotificationUtilsTest: expanded from 12 to 21 tests, adding extractWearNotification
  scenarios (no actions, single reply action, reply-action selection priority, tag capture)
  and group title message-count trimming branch

Build config:
- Add JaCoCo plugin + jacocoUnitTestReport task for coverage reporting
- Enable enableUnitTestCoverage in debug build type

Documentation:
- Add CLAUDE.md with build instructions, test run commands, test architecture overview,
  common issues (JAVA_HOME, Robolectric resource errors, Keystore unavailability),
  and note on JaCoCo/Robolectric incompatibility with offline instrumentation
New tests (+56 unit tests, 211 → 267 total):

PreferencesManagerTest (+38):
- Show notification pref (new-install init, get/set)
- GitHub release notes ID, last purged time
- Play store rating status and timestamp
- Foreground service notification pref
- Reply-to names and custom reply names (StringSet)
- Generic getString / saveString
- Subscription status last checked, product name
- Deprecated isOpenAIRepliesEnabled / setEnableOpenAIReplies
- Enabled apps: saveEnabledApps(String), saveEnabledApps(App),
  getEnabledApps, isAppEnabled(String), isAppEnabled(App)
- isFirstInstall static method

CustomRepliesDataTest (+14):
- getTextToSendOrElse: non-AI, automatic AI, BYOK,
  attribution on/off, AI result vs custom reply
- set(Editable): null, valid, empty
- isValidCustomReply(Editable): null, valid, empty,
  too-long, at-max-length

NotificationUtilsTest (+4):
- extractWearNotification picks from WearableExtender
- showAccessRevokedNotification: smoke test, channel
  creation, notification posted (via ShadowNotificationManager)

Production fix:
- CustomRepliesData.getTextToSendOrElse() now wraps
  getString() calls in try-catch with hardcoded fallbacks,
  consistent with the init() pattern used throughout the
  codebase, enabling unit testing and improving robustness.
MainActivityTest: remove duplicate lifecycle test; add 8 new Espresso
checks for ai_reply_text, btn_edit, bottom_nav, all four filter rows,
and a test verifying the auto-reply switch state matches PreferencesManager.

PreferencesManagerInstrumentedTest: clear SharedPreferences in setUp and
tearDown so tests are fully isolated and order-independent; fix
serviceEnabledDefaultsToFalseOnFreshInstance to be reliable from a
known-clean state; fix setAndGetServiceEnabled to assert from a known
starting point rather than toggling an unknown value.
@adeekshith adeekshith changed the title Improve Unit Test and Instrumentation Test Coverage tests: Improve Unit Test and Instrumentation Test Coverage Mar 17, 2026
Add 9 new test files covering previously untested classes:
- AppTest, ContactHolderTest, AppPackageTest (plain JUnit)
- OpenAIHelperTest, NotificationHelperTest, DbUtilsTest,
  ContactsHelperTest, AutoStartHelperTest (Robolectric)

Add edge cases to 4 existing test files:
- PreferencesManagerTest: boundary timestamps, empty sets, concurrent reset
- NotificationUtilsTest: emoji/RTL titles, null group title NPE (documents bug),
  future timestamps, actions without RemoteInput
- CustomRepliesDataTest: fresh instance get(), max-length reply
- AppUtilsTest: singleton identity, reset, empty package name

Add resetInstance() to NotificationHelper for test isolation,
consistent with PreferencesManager/AppUtils/CustomRepliesData pattern.
Add 5 new instrumentation test files:
- SettingsActivityTest: launch, toolbar, fragment container, up button
- AboutActivityTest: launch, version display, privacy/developer links
- DonationActivityTest: launch, root layout, fragment container
- CustomReplyEditorActivityTest: reply method cards, save button, toolbar
- CustomRepliesDataInstrumentedTest: real-device SharedPreferences persistence

Expand MainActivityTest with bottom nav items, filter description
visibility/content checks, and proper state isolation in setUp/tearDown.
… tests

New test files:
- SubscriptionInfoActivityTest: launch with all modes (MANAGE/UPGRADE),
  toolbar, state views (loading/active/inactive), subscription UI elements
- OtherAiConfigurationActivityTest: launch, form fields (provider dropdown,
  API key, model selector, system prompt), save button, base URL visibility

Fixes for GooglePlay flavor compatibility:
- MainActivityTest: set guest mode before launch to bypass login redirect
- ExampleInstrumentedTest: accept both flavor package names

All 112 instrumentation tests pass on both Default and GooglePlay flavors.
- Upgrade JDK from 17 to 21 to match project requirements
- Replace generic ./gradlew test with explicit flavor targets
  (testDefaultDebugUnitTest + testGooglePlayDebugUnitTest)
- Add instrumentation test job running on API 28 emulator
- Add JaCoCo coverage report generation and artifact upload
- Add Gradle caching via gradle/actions/setup-gradle
- Fix deprecated set-output syntax in APK upload steps
@adeekshith adeekshith requested a review from spuday90 March 17, 2026 05:37
On Android 13+ (API 33+), MainFragment requests POST_NOTIFICATIONS
in onCreateView, which shows a system dialog that blocks Espresso.
Use UiAutomation.grantRuntimePermission() in setUp to prevent this.
- NotificationHelperTest: check all notifications for WhatsApp title
  prefix instead of assuming first notification is the individual one
  (ordering differs between local and CI Robolectric environments)
- DonationActivityTest: remove recreation test that crashes due to
  DonationFragment Retrofit callback calling requireContext() after
  fragment detaches, which kills the test process
The save button is below the fold on CI emulator (API 28) and
scrollTo() is unreliable inside CoordinatorLayout. Use findViewById
to verify the button exists in the layout instead.
@adeekshith adeekshith changed the title tests: Improve Unit Test and Instrumentation Test Coverage chore: Improve Unit Test and Instrumentation Test Coverage Mar 17, 2026
@spuday90 spuday90 requested a review from Copilot March 18, 2026 02:00
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR focuses on increasing test coverage across core model/utility logic (unit + Robolectric) and key screens (instrumentation), while adding JaCoCo reporting and expanding CI to build/test variants and publish artifacts.

Changes:

  • Added extensive new unit/Robolectric tests for network models, preferences, notifications, helpers, and data models.
  • Added multiple new Android instrumentation tests for major Activities and improved flavor-agnostic checks.
  • Enabled JaCoCo + unit-test coverage reporting and updated GitHub Actions workflow to build, test, run emulator tests, and upload artifacts/reports.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
gradle/libs.versions.toml Adds mockito-kotlin version + library alias for Kotlin-friendly mocking.
app/build.gradle.kts Enables debug unit test coverage, adds JaCoCo report task, adds mockito-kotlin test dep.
app/src/main/java/com/parishod/watomatic/model/utils/NotificationHelper.java Adds resetInstance() to support test isolation.
app/src/main/java/com/parishod/watomatic/model/preferences/PreferencesManager.java Adds safer defaults for preference keys, adds resetInstance(), and broadens exception handling for tests.
app/src/main/java/com/parishod/watomatic/model/CustomRepliesData.java Adds resetInstance() and resource fallback strings for unit-test environments.
app/src/test/java/com/parishod/watomatic/network/model/NetworkModelsTest.kt Adds JVM unit tests for OpenAI/Atomatic network model POJOs.
app/src/test/java/com/parishod/watomatic/model/utils/OpenAIHelperTest.kt Adds Robolectric tests for OpenAI model caching behavior.
app/src/test/java/com/parishod/watomatic/model/utils/NotificationUtilsTest.kt Adds Robolectric tests for notification parsing/extraction logic and edge cases.
app/src/test/java/com/parishod/watomatic/model/utils/NotificationHelperTest.kt Adds Robolectric tests for notification posting/grouping behavior.
app/src/test/java/com/parishod/watomatic/model/utils/DbUtilsTest.kt Adds Robolectric smoke/edge tests for DB utility behavior.
app/src/test/java/com/parishod/watomatic/model/utils/ContactsHelperTest.kt Adds Robolectric tests around contacts permissions + custom contacts behavior.
app/src/test/java/com/parishod/watomatic/model/utils/AutoStartHelperTest.kt Adds Robolectric smoke tests for autostart permission flow.
app/src/test/java/com/parishod/watomatic/model/utils/AppUtilsTest.java Expands AppUtils tests (singleton + edge case).
app/src/test/java/com/parishod/watomatic/model/preferences/PreferencesManagerTest.kt Adds large Robolectric test suite covering most preference behaviors and edge cases.
app/src/test/java/com/parishod/watomatic/model/logs/MessageLogTest.kt Adds unit tests for MessageLog entity behavior and UUID generation.
app/src/test/java/com/parishod/watomatic/model/logs/AppPackageTest.kt Adds unit tests for AppPackage entity.
app/src/test/java/com/parishod/watomatic/model/data/ContactHolderTest.kt Adds unit tests for ContactHolder constructors/flags.
app/src/test/java/com/parishod/watomatic/model/GithubReleaseNotesTest.kt Adds Robolectric parcelable tests for GithubReleaseNotes.
app/src/test/java/com/parishod/watomatic/model/CustomRepliesDataTest.kt Adds Robolectric tests for validation, persistence, and AI/attribution behavior.
app/src/test/java/com/parishod/watomatic/model/ConstantsTest.kt Adds unit tests for supported apps/providers/constants invariants.
app/src/test/java/com/parishod/watomatic/model/AppTest.kt Adds unit tests for App data class equality/copy/toString.
app/src/androidTest/java/com/parishod/watomatic/SubscriptionInfoActivityTest.kt Adds Espresso/ActivityScenario coverage for subscription UI wiring.
app/src/androidTest/java/com/parishod/watomatic/SettingsActivityTest.kt Adds Espresso coverage for settings screen basics + recreation.
app/src/androidTest/java/com/parishod/watomatic/PreferencesManagerInstrumentedTest.kt Adds device-level preferences/keystore behavior verification.
app/src/androidTest/java/com/parishod/watomatic/OtherAiConfigurationActivityTest.kt Adds Espresso coverage for BYOK/other-provider configuration UI.
app/src/androidTest/java/com/parishod/watomatic/MainActivityTest.kt Adds Espresso coverage for MainActivity UI presence + permission handling.
app/src/androidTest/java/com/parishod/watomatic/ExampleInstrumentedTest.java Makes package-name assertion flavor-agnostic.
app/src/androidTest/java/com/parishod/watomatic/DonationActivityTest.kt Adds Espresso coverage for donation screen basics.
app/src/androidTest/java/com/parishod/watomatic/CustomReplyEditorActivityTest.kt Adds Espresso coverage for custom reply editor UI.
app/src/androidTest/java/com/parishod/watomatic/CustomRepliesDataInstrumentedTest.kt Adds device-level persistence tests for CustomRepliesData.
app/src/androidTest/java/com/parishod/watomatic/AboutActivityTest.kt Adds Espresso coverage for about screen UI + recreation.
CLAUDE.md Adds a developer guide describing project structure, test commands, and coverage caveats.
.github/workflows/android.yml Expands CI to build both flavors, run unit + instrumentation tests, and upload artifacts/reports.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@adeekshith
Copy link
Owner Author

Using JUnit assertions seems valid point based on its reasoning. Will plan to do it in another PR is it is relevant

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.

3 participants