Skip to content

Testing Documentation

YewonDanaLee edited this page Oct 21, 2026 · 2 revisions

Testing Documentation

Document Revision History

Version Date Key Changes Author
v0.1.0 2026-10-21 Iteration 2: Test Responsibility & Schedule, Unit & Integration Testing (plan and first results) Yewon Lee

1. Test Responsibility & Schedule (Iteration 2)

Who

Whoever writes a feature also writes its tests, in the same PR. Each part has one person who keeps its tests working.

Component (layer) Files Maintainer
Backend: route generation & street graph api/route_algorithm/algorithm.py, street_graph.py Yewon Lee
Backend: elevation, scoring, LLM briefing api/route_algorithm/elevation.py, scoring.py, briefing.py, llm.py Yewon Lee
Backend: traffic signal counting signal counting in algorithm.py SoonYoung Park
Backend: accounts API api/views/auth.py Anton (log-in, Google, log-out), Yewon Lee (sign-up validation)
Backend: saved routes API api/views/routes.py, api/models.py Anton
Backend: place search api/services/tmap.py, place_translation.py, api/views/places.py Yewon Lee
Android Model (data layer) data/remote, data/repository, data/auth Yewon Lee; elevation in RouteRepository: SoonYoung Park
Android ViewModel AuthViewModel, MyPageViewModel, route options in RouteViewModel Yewon Lee
Android ViewModel (elevation) elevation and slope parts of RouteViewModel SoonYoung Park
Android View (Compose UI) ui/**/*Screen.kt, RouteMap.kt Screen authors (manual testing)

When

  • Before merging a PR, the author runs both test suites and everything has to pass. If the PR touches shared code, the reviewer runs them too.
    • Backend: python manage.py test
    • Android: ./gradlew :app:testDebugUnitTest
  • At the end of each iteration we run all tests and both coverage reports on the latest iteration-N-demo commit and update the Results below.
  • We don't have CI yet. We plan to run the tests on every PR with GitHub Actions in Iteration 3.

2. Unit Testing & Integration Testing (starting from Iteration 2)

Plan

Frameworks

Component Test framework Mocking / fakes Coverage tool
Backend (Django) Django test runner (unittest), DRF APITestCase unittest.mock, fake street grid (api/tests/fakes.py), recorded TMAP responses (api/tests/data) coverage.py 7.16.2
Android JUnit 4, kotlinx-coroutines-test FakeApiService, fake elevation API, OkHttp MockWebServer, MainDispatcherRule JaCoCo (Android Gradle plugin)

Coverage goals by architecture (line coverage)

We set these before measuring anything.

Layer Target Why
Backend route algorithm (api/route_algorithm) 85% Main logic of the app (route shape, elevation, score, briefing). Plain Python, easy to test alone.
Backend API & services (api/views, api/services, api/models.py) 80% Input checks and error responses. Some branches only happen when an outside service fails.
Android ViewModel 60% Screen state (options, save, rename, delete). Can run on the JVM with fakes.
Android Model (data.*) 50% Mostly thin Retrofit / DataStore code. The real logic is in the interceptor and repositories.
Android View (Compose UI) no target Needs instrumented UI tests. For now we check screens by hand on the emulator.

Scope & exclusions

  • Excluded from backend coverage: api/tests/*, api/migrations/* (backend/.coveragerc).
  • api/management/commands/build_street_graph.py is counted but has no target. It downloads a 114MB file, so we run it by hand. The code it calls (street_graph.py) has unit tests.
  • Android: the Gradle plugin already leaves out generated code (R, BuildConfig). Compose UI has no target.
  • Tests never call outside services. Overpass, Open-Meteo, Open-Elevation, Gemini, Google and TMAP are mocked or faked. The backend uses Django's test database.
  • api/tests/test_route_flow.py uses the real Seoul street graph. If backend/data/street_graph/seoul_walk.pkl isn't there, it is skipped.

Reproducible commands

Backend (Python 3.14, from backend/):

python -m venv venv && source venv/bin/activate
pip install -r requirements.txt -r requirements-dev.txt
python manage.py migrate
python manage.py build_street_graph        # needed for the 3 integration tests; otherwise they are skipped
GOOGLE_CLIENT_ID=test coverage run manage.py test
coverage report                            # coverage html for an HTML report

GOOGLE_CLIENT_ID just has to exist (any value works). Other API keys aren't needed because outside calls are mocked.

Android (Gradle 9.5.0 wrapper, JDK 17+, from android_app/):

./gradlew :app:testDebugUnitTest
./gradlew :app:createDebugUnitTestCoverageReport
# report: app/build/reports/coverage/test/debug/index.html

Results

Iteration 2: 2026-10-21, commit 496a542 (branch iteration-2/test/app-unit-tests, PR #21)

Component Frameworks Target Actual Date Command / Report
Backend route algorithm Django test runner, mock, coverage.py 85% 88.0% (574/652) ✅ 10/21 coverage run manage.py test
Backend API & services Django test runner, mock, coverage.py 80% 87.4% (347/397) ✅ 10/21 coverage run manage.py test
Android Model JUnit, MockWebServer, JaCoCo 50% 69.5% (191/275) ✅ 10/21 ./gradlew :app:createDebugUnitTestCoverageReport
Android ViewModel JUnit, coroutines-test, JaCoCo 60% 54.6% (288/527) ❌ 10/21 ./gradlew :app:createDebugUnitTestCoverageReport
Android View — — 6.3% (82/1311) 10/21 same

Totals: backend 85% (925/1094 statements), Android 26.5% (561/2113 lines).

Test counts

  • Backend: 103 tests, 103 passed, 0 failed, 0 skipped. This is with the Seoul graph built. Without it, the 3 tests in test_route_flow.py are skipped.
  • Android: 34 tests, 34 passed, 0 failed, 0 skipped.
Area Tests What is checked
Backend test_algorithm.py 11 Loop / point-to-point / shortest-path fallback, 3 distinct options ranked by score, measured climb and signals in the briefing, routes without elevation, traffic signal counting
Backend test_generate_route.py 15 Route API validation, languages, end point, options with their own temporary route IDs, map server errors (503)
Backend test_elevation.py 12 50m sampling, total climb, uphill sections, batching, lookup errors, score formula
Backend test_street_graph.py 7 Walking filter, building from an OSM file, traffic signals, cutting out an area, Overpass fallback
Backend test_route_flow.py (integration) 3 Start point → loop → elevation / signals → scoring → briefing → save → saved list on the real Seoul graph; point-to-point; no elevation
Backend auth / routes / places / LLM / briefing / crossings 55 test_auth 8, test_route_names 5, test_places 11, test_place_translation 8, test_llm 7, test_briefing 10, test_crossings 6
Android RouteViewModelOptionsTest 10 Input validation, options, switching, save state per option, retry, reset
Android MyPageViewModelTest 7 Rename, swipe-to-delete with rollback on failure, reset
Android AuthInterceptorTest 6 Token header, expired-session detection
Android ServerMessageTest 4 Server error → localized message mapping
Android RouteRepositoryTest, RouteGeometryUtilsTest, ExampleUnitTest 7 Slope calculation and route splitting for slope colors

Android ViewModel is below target (54.6%, target 60%)

  • AuthViewModel is at 0%. It makes its repository from the Android Application and DataStore, so it can't run in a plain JVM test.
  • The elevation summary text in RouteViewModel has no tests yet.
  • In Iteration 3 we will pass the repository into AuthViewModel (or add Robolectric) and test sign-up checks and session handling. SoonYoung will add tests for the elevation summary.

Coverage reports

Backend (coverage.py):

Backend coverage report

Android (JaCoCo):

Android coverage report

Android unit test results:

Android unit test results


3. AI Module Testing (starting from Iteration 3)

To be completed in Iteration 3.

4. Acceptance Testing (starting from Iteration 3)

To be completed in Iteration 3 (plan) and Iteration 4 (results).

5. Alpha & Beta Testing (Iteration 5)

To be completed in Iteration 5.