feat(testing): Add testing infrastructure with Kover and test utilities#3520
Conversation
- Add Kover plugin for code coverage reporting with exclusions for generated code (DI factories, databinding, etc.) - Create common:test-utils module with shared test infrastructure: - TestDispatcherRule for coroutines testing - RxSchedulerRule for RxJava testing - FlowTestExtensions with Turbine-based helpers - TestDataFactory for Quran-specific test fixtures - Base test classes for coroutines, RxJava, and combined tests - Add MockK dependency for Kotlin-first mocking - Add comprehensive TESTING_STRATEGY.md documenting the testing approach This establishes the foundation for comprehensive test coverage following TDD principles and the testing pyramid approach.
Expand QuranInfo test coverage from 6 to 46 tests covering: - Juz calculations (boundaries, within-juz, display juz) - Page validation (valid/invalid pages) - Sura operations (page numbers, sura from page, ayah counts) - Ayah operations (IDs, lookups, diffs) - Page lookups (bounds, verse ranges, sura/ayah to page) - Rub'/Quarter and Manzil lookups - Dual page mapping (single to dual, dual to single, round-trip) - Position/navigation calculations (ViewPager) - Data integrity verification against data source Tests include boundary conditions, invalid inputs, and edge cases to ensure robustness of the core Quran metadata operations.
Per maintainer feedback, remove MockK dependency and update TESTING_STRATEGY.md to reflect fakes-first approach: - Remove MockK from libs.versions.toml - Remove MockK from app and test-utils dependencies - Update all examples to use fake implementations - Add section explaining fakes vs mocks philosophy - Update test templates to use fakes pattern
Phase A (P0): - Rewrite TestDataFactory to use real domain models (SuraAyah, Bookmark, Tag, RecentPage) instead of duplicate test classes - Add dependency on common:data module for real model access Phase B (P1): - Fix RxSchedulerRule exception handling: track RxAndroid availability state explicitly, only catch NoClassDefFoundError (expected when RxAndroid not in classpath) - Fix Kover exclusion patterns: change *Module to *_Module and *Module_* to avoid excluding real business classes Phase C (P2): - Remove unused base test classes (BaseCoroutineTest, BaseRxTest, BaseCombinedTest) - favor composition over inheritance - Trim TESTING_STRATEGY.md from 1042 to 304 lines (71% reduction)
- AudioUpdaterTest: Update QariItem constructor calls to include opusUrl parameter (null) added in recent refactor - GaplessAudioInfoCommandTest: Add missing allowedExtensions parameter to gaplessDownloads() calls - GappedAudioInfoCommandTest: Add missing allowedExtensions parameter to gappedDownloads() calls These tests were broken before this PR due to production code changes that weren't reflected in the test files.
|
|
Upgraded Dependencies |
ahmedre
left a comment
There was a problem hiding this comment.
جزاكم الله خيراً looks good
2 minor comments
| /** | ||
| * Creates multiple bookmarks for testing. | ||
| */ | ||
| fun createBookmarks(count: Int): List<Bookmark> = |
There was a problem hiding this comment.
do these need to be valid since this is likely to generate incorrect (invalid) sura/ayah bookmarks.
There was a problem hiding this comment.
Good catch! You're right - removed for now. Will add back in Phase 1 when implementing BookmarksDaoImpl tests (15+ tests). Fixed in 4e1dc3c.
| truth = { module = "com.google.truth:truth", version.ref = "truthVersion" } | ||
| turbine = { module = "app.cash.turbine:turbine-jvm", version.ref = "turbineVersion" } | ||
| kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutinesVersion" } | ||
| sqldelight-sqlite-driver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" } |
There was a problem hiding this comment.
You're right - not needed yet. Removed for now, will add back when implementing BookmarksDaoImpl and database integration tests. Fixed in 4e1dc3c.
|
would also be nice to kill Mockito in the future in sha' Allah |
- Remove createBookmarks() function (unused, will add in Phase 1 when needed) - Remove sqldelight-sqlite-driver dependency (will add for BookmarksDao tests) Addresses review feedback from @ahmedre
Future Work: Mockito RemovalPlanning to remove Mockito as part of Phase 2 and/or 3, in sha' Allah. Current state:
Strategy:
This approach ensures fakes are built with real use cases rather than upfront guesswork. |
|
|
Upgraded Dependencies |
Summary
Implements Phase 1 of the testing infrastructure initiative as discussed in #3516.
common:test-utilsmodule with shared testing utilitiesTestDataFactoryusing real domain models (SuraAyah, Bookmark, Tag, RecentPage)RxSchedulerRulefor synchronous RxJava testingTestDispatcherRulefor coroutine testingTESTING_STRATEGY.mddocumentationChanges
Test Results
Test Plan
Closes #3516