Skip to Content
OverviewTesting & QA

Testing & QA

⚠️ Reality check (2026-06): The mobile consolidation removed the Hilt-based test-core module. Post-consolidation, client test coverage is near-zero (shared has ~4 test files for 491 sources; composeApp 0/287; androidApp 0/2). Only the server module has meaningful coverage (~53 files). Testing infrastructure is undergoing a rebuild — see tech-debt/testing.md for the current gap. This document describes the target state; consult the tech-debt register for the actual state.

This document describes the testing strategy and quality assurance practices for Oter.

Overview

Testing layers, current coverage reality, and aspirational targets.

Testing Philosophy

Current priority (2026-06): Rebuild client test coverage from near-zero to meaningful levels. The Hilt-based test-core module was removed during mobile consolidation; a koin-test replacement is being established.

Oter follows a pragmatic testing approach focused on:

  • Critical paths: Balance prediction engine and financial calculations
  • User workflows: End-to-end user journeys
  • Data integrity: Financial data accuracy
  • Cross-platform consistency: Shared code behavior across platforms

Current Testing Structure

Unit Tests

Location: */src/test/ directories

Coverage Areas:

  • Business logic in service layers
  • Utility functions
  • Data transformations
  • Calculation algorithms

Example Test Structure:

class TransactionServiceTest { @Test fun `calculate starting balance correctly`() { // Arrange val account = Account(initialBalance = 1000.0) val transactions = listOf( Transaction(amount = 100.0, type = INCOME), Transaction(amount = 50.0, type = EXPENSE) ) // Act val balance = calculateBalance(account, transactions) // Assert assertEquals(1050.0, balance) } }

Test Framework:

  • Kotlin Test: Standard Kotlin testing framework
  • JUnit: For JVM-based tests
  • MockK: Mocking framework for Kotlin (previous)
  • koin-test: Koin-based test utilities (post-consolidation DI replacement — see tech-debt/testing.md)

Integration Tests

Location: server/src/test/ (server-side)

Coverage Areas:

  • API endpoint testing
  • Database operations
  • Service layer integration
  • Repository layer

Test Framework:

  • Ktor Test Host: For testing Ktor routes
  • Testcontainers: For database testing (if used)
  • Exposed Test: For database transaction testing

Example:

class FinanceRoutingTest { @Test fun `POST /finance/predict returns valid prediction`() = testApplication { // Setup test data // Make request // Assert response } }

End-to-End Tests

Status: Limited coverage

Coverage Areas:

  • Critical user workflows
  • Cross-platform behavior
  • UI interactions

Challenges:

  • Multi-platform testing complexity
  • Compose Multiplatform testing tools
  • Test data management

Testing Strategy by Module

Prediction Engine Testing

Priority: Highest

Critical Test Cases:

  1. Starting Balance Calculation

    • Correct calculation from initial balance + transactions
    • Handles multiple accounts
    • Handles empty transaction history
  2. Date Point Generation

    • Daily granularity generates correct dates
    • Weekly granularity generates correct dates
    • Monthly granularity generates correct dates
    • Handles date range boundaries
  3. Transaction Aggregation

    • Committed transactions correctly aggregated
    • Scheduled transactions correctly projected
    • Periodic spends correctly applied
    • Past month replication works correctly
  4. Scenario Generation

    • Base scenario matches expected
    • Optimistic scenario applies positive noise
    • Pessimistic scenario applies negative noise
    • Noise percentage correctly applied
  5. Edge Cases

    • No transaction history
    • Very long date ranges
    • Negative balances
    • Multiple accounts with transfers

Test Data:

  • Synthetic transaction data
  • Known-good prediction results
  • Edge case scenarios

Finance Module Testing

Account tests (server):

  • AccountBalanceCalculatorTest — unit tests for signed amounts and balance formula
  • AccountDBTest — integration tests for CRUD, derived balance, soft-delete, getTotalBalance (Postgres localhost:5431/testdb)
  • AccountRepositoryTest — verifies update forwards userId and accountId in correct order

See Accounts.

Test Areas:

  • Transaction CRUD operations
  • Account management
  • Budget calculations
  • Savings goal tracking
  • Category keyword matching

Test Cases:

  • Create transaction with valid data
  • Reject invalid transaction amounts
  • Calculate budget progress correctly
  • Derived account balance reflects income/expense after transactions (balance is computed on read, not stored per transaction)
  • Soft-deleted accounts excluded from list and total balance

Data Layer Testing

Test Areas:

  • Repository methods
  • Database queries
  • Data conversions
  • Transaction handling

Test Approach:

  • In-memory database for fast tests
  • Test transactions (rollback after each test)
  • Verify data integrity

Test Organization

Naming Conventions

Tests follow a consistent naming pattern:

class FeatureServiceTest { @Test fun `methodName_condition_expectedResult`() { // Test implementation } }

Example:

@Test fun `calculateBalance_withIncomeAndExpense_returnsCorrectBalance`() { // Test }

Test File Structure (post-consolidation)

shared/ src/commonTest/ kotlin/com/esteban/ruano/oter/ services/ FinanceServiceTest.kt utils/ DateUIUtilsTest.kt server/ src/test/ kotlin/com/esteban/ruano/ service/ AccountBalanceCalculatorTest.kt routing/ FinanceRoutingTest.kt repository/ AccountDBTest.kt

Test Data Management

Approach:

  • Test fixtures: Reusable test data builders
  • Factories: Object factories for creating test entities
  • Fixtures: JSON files for complex test data

Example:

object TestFixtures { fun createTransaction( amount: Double = 100.0, type: TransactionType = EXPENSE ): Transaction { return Transaction( amount = amount, type = type, // ... other fields with defaults ) } }

Running Tests

Server Tests

# Run all server tests ./gradlew :server:test # Run specific test class ./gradlew :server:test --tests TransactionServiceTest # Run with coverage ./gradlew :server:test jacocoTestReport

Shared Module Tests

# Run shared module tests ./gradlew :shared:test

All Tests

# Run all tests across modules ./gradlew test

Code Coverage

Current Coverage (as of 2026-06)

ModuleTest FilesSourcesApprox. Coverage
server~53~N/AMeaningful
shared~4~491≈ 1%
composeApp0~2870%
androidApp0~20%

See tech-debt/testing.md for the full gap analysis and rebuild plan.

Coverage Targets (aspirational)

  • All modules: 70%+ (long-term)
  • Prediction Engine: 90%+
  • Finance Services: 80%+

Coverage Tools

  • JaCoCo: Code coverage for JVM modules (server)
  • Kover: Kotlin code coverage (alternative for client modules)

Coverage Reports

# Generate coverage report ./gradlew test jacocoTestReport # View report open build/reports/jacoco/test/html/index.html

Quality Assurance Practices

Code Review

Process:

  1. All code changes require review
  2. At least one approval required
  3. Automated checks must pass
  4. Test coverage must not decrease

Review Checklist:

  • Tests added/updated (or documented rationale for skipping)
  • Documentation updated
  • No breaking changes (or documented)
  • Performance considered
  • Security considered

Static Analysis

Tools:

  • Detekt: Kotlin code analysis
  • ktlint: Code style checking
  • Android Lint: Android-specific checks

Configuration:

# Run static analysis ./gradlew detekt ./gradlew ktlintCheck

Continuous Integration

CI Pipeline:

  1. Lint: Code style and static analysis
  2. Build: Compile all modules
  3. Test: Run all tests
  4. Coverage: Generate coverage reports
  5. Deploy: Deploy to staging (on main branch)

Manual Testing

Test Scenarios:

  • User registration and login
  • Create and edit transactions
  • Generate balance predictions
  • Import transactions
  • Manage accounts and budgets

Test Devices:

  • Desktop (Windows, macOS, Linux)
  • Android (various versions)
  • iOS (various versions)
  • Web (Chrome, Firefox, Safari)

Testing Best Practices

Test Isolation

  • Each test is independent
  • No shared state between tests
  • Database transactions rolled back
  • Mock external dependencies

Test Data

  • Use realistic but synthetic data
  • Avoid hardcoded credentials
  • Clean up test data after tests
  • Use factories for test data creation

Assertions

  • Clear assertion messages
  • Test one thing per test
  • Use descriptive test names
  • Verify both positive and negative cases

Performance Testing

Areas:

  • Prediction generation performance
  • Database query performance
  • API response times
  • Large dataset handling

Tools:

  • JMeter for API load testing
  • Custom benchmarks for algorithms
  • Profiling tools (JProfiler, YourKit)

Future Testing Improvements

Immediate Priority (2026)

  1. Rebuild client test infrastructure: Establish koin-test patterns, shared test fixtures, and DI test modules for shared and composeApp
  2. Migrate server tests: The server’s existing test suite (~53 files) should be adapted to any new DI conventions introduced by the consolidation
  3. Cover critical paths first: Balance prediction engine, finance calculations, auth flows
  4. Add CI gate: Block merges on test failures once baseline coverage exists

Test Coverage Goals

  • Unit Tests: 80%+ coverage (long-term)
  • Integration Tests: Critical paths covered
  • E2E Tests: Major user workflows

Testing Tools

  • Compose Testing: UI testing for Compose Multiplatform
  • Screenshot Testing: Visual regression testing
  • Property-Based Testing: Hypothesis-style testing for calculations
  • koin-test: DI-aware testing replacing the removed Hilt test-core

Test Automation

  • Automated E2E Tests: CI/CD pipeline integration
  • Performance Benchmarks: Automated performance regression detection
  • Security Testing: Automated vulnerability scanning

Test Infrastructure

  • Test Containers: Real database testing (server)
  • Mock Server: External API mocking (WireMock / MockServer)
  • Test Data Management: Centralized test data / factories

Bug Reporting

Bug Report Template

**Description:** Clear description of the issue **Steps to Reproduce:** 1. Step one 2. Step two 3. ... **Expected Behavior:** What should happen **Actual Behavior:** What actually happens **Environment:** - Platform: Desktop/Android/iOS/Web - Version: X.Y.Z - OS: ... **Screenshots:** If applicable **Logs:** Relevant error logs

Bug Triage

Priority Levels:

  • P0: Critical (data loss, security)
  • P1: High (broken feature)
  • P2: Medium (minor issue)
  • P3: Low (cosmetic)

Labels:

  • bug: Confirmed bug
  • enhancement: Feature request
  • question: Question/help needed
  • platform-specific: Issue on specific platform