Testing Philosophy
The testing approach follows these core principles:- Test Isolation: Each layer is tested independently with minimal dependencies
- Test Utilities: Reusable test doubles and utilities reduce boilerplate
- Real Examples: Tests use concrete examples that document expected behavior
- Fast Feedback: Unit tests run quickly without external dependencies
Test Pyramid
The project follows the testing pyramid approach:Unit Tests (Base)
The foundation consists of comprehensive unit tests for:
- Domain models and business logic
- Use cases with test repositories
- Data repositories with test cache providers
- ViewModels with test use cases
Integration Tests (Middle)
Integration tests verify layer interactions:
- Repository tests with real cache implementations
- Network layer tests with NetMock
- Flow-based state management tests
Testing Strategy Per Layer
Domain Layer Testing
The domain layer contains pure business logic that is highly testable.Use Cases
Use Cases
Use cases are tested with test implementations of repositories and other dependencies.Example: Testing
AddToWishlistUseCaseDomain Models
Domain Models
Domain models with business logic are tested to verify their behavior.Example: Testing
Cart model calculationsValue Objects
Value Objects
Value objects with validation logic are thoroughly tested.Example: Testing
Email validationData Layer Testing
The data layer is tested using test implementations of infrastructure dependencies.Repository Tests
Repositories are tested with
TestCacheProvider and NetMock for network calls.See RealCartRepositoryTest.ktNetwork Integration
Network calls are tested using NetMock library for deterministic HTTP responses.See RealUserRepositoryTest.kt
Presentation Layer Testing
ViewModels are tested using test implementations of use cases and theFlowTestObserver.
Example: Testing RealCartViewModel
The
MainCoroutineRule ensures coroutines run on the test dispatcher for deterministic testing.Coverage Approach
The project prioritizes meaningful coverage over percentage targets. Each piece of business logic is tested, while framework code and simple delegations may be skipped.
What to Test
- Business logic in domain models and use cases
- Repository implementations with cache and network interactions
- ViewModel state management and user interactions
- Validation logic in value objects
- Error handling and edge cases
What Not to Test
- Simple data classes without logic
- Framework code (Compose UI, dependency injection)
- Pure delegation without transformation
- Generated code (serialization, Room entities)
Test Organization
Tests are co-located with source code:Test Naming Convention
All tests follow the pattern:EXPECT item added to cart WHEN not presentEXPECT quantity increased WHEN item already present in cartEXPECT invalid email error WHEN login request has invalid email
Next Steps
Unit Testing
Learn how to write unit tests for each architectural layer
Test Utilities
Explore reusable test utilities and test doubles