Skip to content

Testing Documentation

최주현 edited this page Oct 22, 2026 · 8 revisions

Testing Documentation

1. Test Responsibility & Schedule

1.1 Who

Component Team member responsible for writing and maintaining tests
Authentication, profile and legacy-data import Ki Hwan Kim
Wardrobe analysis and labels Hyeon U Jung, Dongkun Moon
Recommendation and outfit APIs, and their Android screens (home, Codibook (코디북), garment labels, front photo) Dongkun Moon
Conversational outfit editing (chat API and Android chat screen) Juhyeon Choi
Body analysis: pose pipeline, measurement API and Android client Dongkun Moon
Android client Hyeon U Jung, Juhyeon Choi
Coverage configuration and CI coverage reports Dongkun Moon

Policy for new code: The author of each new feature writes its tests and submits them in the same PR as the implementation. Relevant tests are updated whenever the feature changes.

1.2 When

Backend CI runs on PRs affecting backend paths and on pushes to main affecting those paths. It runs pytest, Django application tests, a migration check and container/model/health checks.

Frontend CI runs on PRs affecting frontend paths and on pushes to main affecting those paths. It runs Android JVM unit tests and builds the debug APK.

Both workflows also measure coverage on every run (from PR #30). Backend CI writes statement and branch coverage per component to the run summary and uploads the HTML report as the backend-coverage artifact. Frontend CI does the same per Android layer for the JVM unit tests (android-unit-coverage). In Iteration 2 coverage is reported, not enforced: a run does not fail when a number is below its target. Backend CI runs the tests and the report generation as separate steps, so its HTML report is uploaded even when a test fails.

Device (instrumented) tests need an emulator or a phone, so they do not run in CI. They are run locally (section 2.1, device-test command).

Additional test execution schedule: Both CI workflows support manual execution through workflow_dispatch.

Tests required before merging a PR: Should be prepared unit test cases, and also CI workflows.

2. Unit Testing & Integration Testing

2.1 Plan

Frameworks

Component Test frameworks / Mocking libraries Coverage tool
Authentication, profile and legacy-data import Django TestCase/TransactionTestCase, unittest.mock coverage.py 7.16.2 (statements and branches), run around the Django test runner
Wardrobe and outfit APIs Django TestCase/SimpleTestCase/TransactionTestCase, unittest.mock coverage.py 7.16.2, run around the Django test runner
Recommendation logic pytest 9.1.1, fixtures, monkeypatch coverage.py 7.16.2 through pytest-cov 7.1.0
Body analysis (pipeline and measurement API) pytest 9.1.1; FakeEstimator and FakeDetector replace MediaPipe and the clothing detector; synthetic mannequin poses (tests/synthetic.py) coverage.py 7.16.2 through pytest-cov 7.1.0
Android data and presentation layers JUnit 4.13.2, MockWebServer 4.12.0; AndroidX Test and Compose UI Test for device tests JaCoCo 0.8.14 through the Android Gradle Plugin 9.1.1 (enableUnitTestCoverage; enableAndroidTestCoverage with -PandroidTestCoverage)

pytest and the Django test runner write to one coverage data file, so each backend number includes every backend test that reaches that code.

Coverage goals by architectural pattern

Targets are statement or line coverage (C0) and branch coverage (C1). Each target counts all automated tests of that component together: pytest and the Django tests on the backend, and JVM unit tests and device tests merged on Android. The levels follow the reference points from the lecture (60 % acceptable, 75 % commendable, 90 % exemplary): highest for business logic, lowest for UI.

Architectural component / layer Target Reason for target
Backend authentication/profile/import logic C0 ≥ 90 %, C1 ≥ 80 % Security-critical: token checks, account isolation and import conflicts. Pure server logic that the Django test client reaches completely with an in-memory database.
Backend wardrobe/outfit application logic C0 ≥ 85 %, C1 ≥ 75 % Mostly request validation and storage around external calls (Gemini, the landmark model, weather). Those calls are mocked, so some of their failure branches stay uncovered by design.
Recommendation business logic C0 ≥ 90 %, C1 ≥ 80 % The core of the outfit feature. Given labels and the shipped model it is deterministic, so every rule and filter can be unit tested. A mistake here gives wrong outfits instead of a crash, so tests are the main safety net.
Backend body analysis C0 ≥ 90 %, C1 ≥ 80 % The core of the body profile. Deterministic geometry and measurement code, testable with synthetic mannequins and fake pose estimators. Wrong measurements do not crash either.
Android data/repository layer C0 ≥ 75 %, C1 ≥ 50 % Network contracts, JSON parsing and account-scoped storage, all testable on the JVM with MockWebServer. Kotlin adds compiler-generated null-check and when branches that tests cannot reach in a meaningful way, so the branch target is lower.
Android ViewModels C0 ≥ 60 %, C1 ≥ 40 % Screen state and user actions. Coroutines and the Android lifecycle make some paths costly to unit test, so the target is the "acceptable" level.
Android UI C0 ≥ 40 %, no branch target Compose screens are checked by device tests of the key flows and by manual runs on a phone. The Compose compiler adds $changed/$default bitmask branches to every composable, so branch coverage there mostly measures generated code. AR capture needs ARCore, which the emulator does not have.

Scope & exclusions

Component Test scope
Authentication, profile and legacy-data import Registration/login/logout, token validation, account isolation, profile validation and import conflicts/retries
Wardrobe and outfit APIs Garment validation and label persistence; own-wardrobe recommendations, outfit save/list/feedback and error handling
Recommendation logic Label calculation, rules, filtering, search and model-input contracts
Body analysis Keypoints to measurements, the regression and clothing corrections, request validation, image limits and error responses of the analysis API; on Android, response parsing, insights, figure geometry and the stored profile
Android data and presentation layers Authenticated requests, response handling, account-scoped state, onboarding and changed home/wardrobe flows

Tests added in this iteration include backend/apps/users/tests.py, test_security.py, test_imports.py, test_migrations.py, backend/apps/outfits/tests.py, and backend/tests/recommendation/. Existing wardrobe/API tests were modified. Android additions include AuthRepositoryTest.kt, BodyProfileStoreTest.kt, GuestImportRepositoryTest.kt, LocalUserStoreTest.kt and OutfitRepositoryTest.kt. Device-test additions cover authentication, onboarding, home, front-photo and garment-label flows.

Coverage exclusions and reasons:

  • Backend (backend/.coveragerc): only apps/, body_analysis/ and recommendation/ are measured.
    • Not measured: config/ (settings and URL wiring) and scripts/ (offline benchmark, dataset and K-Fashion training scripts). The scripts need the AI Hub data and are evaluated as AI modules from Iteration 3.
    • Left out because they are not app code: migrations, test files, the local test page recommendation/demo/ and the command-line tool body_analysis/cli.py.
    • recommendation/stylist.py, decision.py, intent.py, tryon.py and gemini.py are used only by that test page and offline scripts, not by any API of the app. They go back into the measured set once the app uses them (the chat feature in PR #28 imports stylist.py).
    • Lines if __name__ == "__main__": and raise NotImplementedError are not counted.
  • Android (frontend/scripts/coverage_by_layer.py): the generated classes BuildConfig, R (and their inner classes such as R$string) and ComposableSingletons are left out. Only exact names are matched, so app classes whose names merely start with R (for example RemoteBodyAnalyzer) are counted (fixed in bfe69cd; earlier numbers left them out by mistake). Every other class under com.swpp.stylemate counts. The data layer is com.swpp.stylemate.data.*, the ViewModel layer is every class with ViewModel in its name, and the UI layer is the rest (screens, MainActivity, theme).

Django application tests use an isolated in-memory SQLite database through config.test_settings. Relevant external service calls are patched or replaced with test doubles. Local model contract/inference tests use the required local model files.

External dependencies replaced in each suite:

  • Wardrobe tests patch apps.wardrobe.views.analyze_image, the Gemini HTTP opener and the landmark session where applicable, providing controlled responses or heatmaps instead of paid API requests or live model inference.
  • Authentication/security tests patch time for rate-limit behavior and patch analysis/weather services to verify that rejected requests do not invoke them.
  • Weather API tests patch apps.outfits.views.weather.current.
  • Recommendation-rule/search tests use a small hand-made catalog instead of the external K-Fashion dataset. test_ai.py replaces gemini.generate; model-contract tests load the shipped masked model and exercise actual ONNX inference.
  • Android repository tests use MockWebServer, in-memory session stores and temporary directories instead of the production API and persistent account files.
  • Regression pipeline tests use synthetic mannequin inputs and fake estimators/detectors where applicable. The MediaPipe model-load smoke test uses the real pose model and is conditionally skipped if that file is absent.

Integration tests

Unit tests check one module with its neighbours replaced. The tests below check that two parts work together across a boundary.

Boundary Test
Android app ↔ body analysis API ServerContractTest parses recorded responses of the real server; backend/tests/test_api.py sends photos through the whole pipeline behind the API
Saved garment labels ↔ recommendation model backend/tests/recommendation/test_model_contract.py: every value the label editor can save is a token the model was trained on, and saved labels run through the shipped ONNX model
Outfit API ↔ database and wardrobe backend/apps/outfits/tests.py: recommend, save to Codibook, feedback and ownership checks through the Django test client
Android repositories ↔ backend API contracts AuthRepositoryTest, GuestImportRepositoryTest, OutfitRepositoryTest and RemoteBodyAnalyzerTest against MockWebServer with the server's request and response formats
Screens ↔ ViewModels ↔ local stores Device tests (OnboardingTest, HomeScreenTest, FrontPhotoTest, GarmentLabelFlowTest, WardrobeScreenTest and others)
Backend ↔ production image Backend CI image job: the pose, garment-landmark and recommendation models load and the server answers health checks inside the Docker image
Whole app on a phone Manual run of the full flow at the end of the iteration (sign-in, body profile, AR capture, front photo, labels, home outfits, Codibook), because AR capture needs ARCore and a real camera

Reproducible commands

Environment item Value
Operating system GitHub-hosted Ubuntu runner (ubuntu-latest)
Python version Python 3.12 selected by Backend CI; dependencies are pinned in backend/requirements-dev.txt and backend/requirements.txt
JDK version Temurin JDK 21 selected by Frontend CI
Android SDK / device / emulator App compile/target SDK 36, minimum SDK 26; Gradle wrapper 9.3.1. Frontend CI executes JVM tests without a device/emulator. Device tests were run on the Android Emulator (Medium Phone, Android 16 / API 36, Google Play x86_64 image).
Required environment variables and model files pytest sets DJANGO_SETTINGS_MODULE=config.test_settings through tests/conftest.py; the Django command selects the same settings explicitly. Those settings use in-memory SQLite and an empty Gemini API key. Recommendation model-contract tests require the committed files in backend/recommendation/models/. The optional real MediaPipe pytest smoke test requires backend/models/pose_landmarker_heavy.task; without it, that check is skipped.

Backend commands, executed from backend/ in the prepared Python environment:

python -m pip install -r requirements-dev.txt
python -m pytest -q
python manage.py makemigrations --check --dry-run --settings=config.test_settings
python manage.py test apps.users apps.wardrobe apps.outfits --settings=config.test_settings --noinput

Android unit-test command, executed from frontend/ with the required JDK and Android SDK:

./gradlew --no-daemon testDebugUnitTest

On Windows, use gradlew.bat instead of ./gradlew. If the project path contains non-ASCII characters, map it to a drive letter first (for example subst X: <project path>); otherwise Gradle unit tests fail with ClassNotFoundException.

Backend CI first installs default-libmysqlclient-dev and pkg-config through apt so that the pinned Python dependencies can be built. To include the optional MediaPipe pytest smoke test, download the pose model before running pytest:

mkdir -p models
curl -L -o models/pose_landmarker_heavy.task https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_heavy/float16/latest/pose_landmarker_heavy.task

Frontend CI also runs ./gradlew --no-daemon assembleDebug. Additional Android checks use :app:compileDebugAndroidTestKotlin and :app:lintDebug.

Device-test command and required setup: Start an emulator (or connect a phone with USB debugging) so that adb devices lists it, then run from frontend/:

./gradlew --no-daemon connectedDebugAndroidTest
  • local.properties needs sdk.dir. stylemate.apiBaseUrl is optional: the device tests replace the server with fakes, except the live tests below.
  • Three tests are opt-in because they talk to a real server, and they are skipped otherwise:
    • AuthScreensTest.liveServerRegistrationAfterMismatchRestoresAndLogsInOnPhone needs -Pandroid.testInstrumentationRunnerArguments.authTestUsername=<unused username> and a running development server.
    • GuestImportTest.liveServerImportResumesMapsClothesAndKeepsOriginalsOnPhone needs -Pandroid.testInstrumentationRunnerArguments.importTestUsername=<unused username> and a running development server.
    • GarmentLandmarksTest.localModelAcceptsAnAndroidEncodedFrame needs -Pandroid.testInstrumentationRunnerArguments.landmarkServer=true and an account signed in on the device.
  • The live tests create accounts, so they are never pointed at the shared school server.

Coverage tool versions, configuration, exact collection commands and report paths:

Backend Android
Tool coverage.py 7.16.2 through pytest-cov 7.1.0 (pinned in requirements-dev.txt) JaCoCo 0.8.14 through the Android Gradle Plugin 9.1.1
Configuration backend/.coveragerc: branch = True, measured packages and exclusions frontend/app/build.gradle.kts, debug build type: enableUnitTestCoverage = true; enableAndroidTestCoverage only with -PandroidTestCoverage, because it instruments the debug APK itself
Per-component table backend/scripts/coverage_by_component.py frontend/scripts/coverage_by_layer.py
CI Backend CI: run summary and backend-coverage artifact Frontend CI: run summary and android-unit-coverage artifact (JVM unit tests only)

Backend, from backend/ (pytest --cov starts a new data file, so it runs first):

python -m pytest -q --cov --cov-report=
python -m coverage run --append manage.py test apps.users apps.wardrobe apps.outfits --settings=config.test_settings --noinput
python -m coverage report
python -m coverage html
python -m coverage json -o coverage.json
python scripts/coverage_by_component.py coverage.json

The HTML report is backend/htmlcov/index.html. The last command prints the per-component table used in 2.2.

Android, from frontend/:

# JVM unit tests only (what CI runs)
./gradlew --no-daemon createDebugUnitTestCoverageReport
python scripts/coverage_by_layer.py app/build/reports/coverage/test/debug/report.xml

# JVM unit tests and device tests, merged (needs a running emulator or phone)
./gradlew --no-daemon -PandroidTestCoverage createAggregatedCoverageReport
python scripts/coverage_by_layer.py app/build/intermediates/aggregated_code_coverage_data/global/collectDebugAggregatedCoverage/debugAppAggregatedXmlReport.xml
Android report Path under frontend/app/build/
JVM unit tests reports/coverage/test/debug/index.html
Device tests reports/coverage/androidTest/debug/connected/index.html (-PandroidTestCoverage createDebugAndroidTestCoverageReport)
Merged reports/aggregated_code_coverage_html_report/global/index.html

2.2 Results

Test date, commit hash (or tag), and command used

Item CI run Local run with coverage
Test date 2026-10-18, approximately 16:39–16:43 KST (07:39–07:43 UTC) 2026-10-22 KST
Tested commit hash or tag 7e905fa71f969d504ca541a74324554e628fdd67 for both Backend CI and Frontend CI bc54db0: develop after merging PR #30, i.e. main at 0a3a216 plus the coverage configuration and the test fixes below. The application code is the same as 0a3a216.
Environment GitHub-hosted Ubuntu runner Windows 11, Python 3.11.9, JDK 21.0.10 (Android Studio JBR), Android Emulator Medium Phone (Android 16 / API 36)
Commands used Backend: python -m pytest -q; python manage.py makemigrations --check --dry-run --settings=config.test_settings; python manage.py test apps.users apps.wardrobe apps.outfits --settings=config.test_settings --noinput. Frontend: ./gradlew --no-daemon testDebugUnitTest, followed by ./gradlew --no-daemon assembleDebug. The coverage commands in 2.1 (backend; Android JVM unit tests; Android merged with device tests)

Backend tests, container checks, Android JVM unit tests and the debug APK build passed. Container checks included pose-model loading, wardrobe-model inference, recommendation-model loading and server health checks.

Coverage per component compared against the target

Component / Layer Frameworks Target (C0 / C1) Actual C0 Actual C1 Met Date Command / Report
Backend authentication/profile/import logic Django test runner, unittest.mock, coverage.py 90 % / 80 % 94.7 % (637/673) 86.7 % (196/226) Yes 2026-10-22 Backend coverage commands; backend/htmlcov/index.html
Backend wardrobe/outfit application logic Django test runner, unittest.mock, coverage.py 85 % / 75 % 91.4 % (811/887) 82.9 % (189/228) Yes 2026-10-22 same
Recommendation business logic pytest, pytest-cov 90 % / 80 % 94.8 % (1215/1281) 87.8 % (360/410) Yes 2026-10-22 same
Backend body analysis pytest, pytest-cov 90 % / 80 % 96.3 % (759/788) 85.1 % (126/148) Yes 2026-10-22 same
Android data/repository layer JUnit, MockWebServer, JaCoCo 75 % / 50 % 80.2 % (1046/1305) 55.2 % (560/1015) Yes 2026-10-22 -PandroidTestCoverage createAggregatedCoverageReport; merged report
Android ViewModels JUnit, Compose UI Test, JaCoCo 60 % / 40 % 33.9 % (206/607) 30.0 % (114/380) No 2026-10-22 same
Android UI Compose UI Test, JaCoCo 40 % / – 44.4 % (1508/3393) 31.9 % (716/2244) Yes 2026-10-22 same

Backend in total: 94.3 % of statements and 86.1 % of branches.

On Android, JVM unit tests and device tests reach different layers. The merged numbers above are what the targets compare against:

Android layer JVM unit tests only (C0 / C1) Device tests only (C0 / C1) Merged (C0 / C1)
data 74.1 % / 49.0 % 33.5 % / 18.1 % 80.2 % / 55.2 %
ViewModel 7.2 % / 10.3 % 33.4 % / 28.9 % 33.9 % / 30.0 %
UI 2.1 % / 2.5 % 44.1 % / 30.8 % 44.4 % / 31.9 %

Repeated device-test runs on the same commit differ by up to 0.3 percentage points, because some Compose UI tests take slightly different paths depending on timing. The backend and JVM unit numbers are identical between runs.

Coverage report screenshots (coverage.py and JaCoCo HTML reports). The backend and Android JVM unit reports are identical on f4b15b3 and bc54db0. The Android device-test and merged screenshots come from the first run on f4b15b3, before the OnboardingTest fix, so their totals are about 2 percentage points lower than the table above, which uses bc54db0:

Backend (coverage.py HTML report, pytest and Django tests together):

Backend coverage report

Android, JVM unit tests (JaCoCo):

Android unit-test coverage report

Android, device tests (JaCoCo):

Android device-test coverage report

Android, unit and device tests merged (overview; the per-layer numbers come from coverage_by_layer.py):

Android merged coverage report

Test counts, failures/skips, and follow-up actions

Local test run:

  • Test date: 2026-10-22 KST
  • Tested commit: bc54db0 (develop after PR #30; application code of main at 0a3a216)
Test suite Total Passed Failed Skipped Report / Screenshot
Django users/wardrobe/outfit suites combined 110 110 0 0 Backend coverage report above; validation notes
Backend pytest 142 142 0 0 same (in CI, without the pose model: 141 passed, 1 skipped)
Android JVM unit tests 95 95 0 0 Android unit-test coverage report above
Android UI/instrumentation tests 42 39 0 3 Android device-test coverage report above; JUnit XML in frontend/app/build/outputs/androidTest-results/connected/debug/

Tests per component (same run):

Component Backend tests Android JVM unit tests Android device tests
Authentication, profile and legacy-data import 50 (Django, apps.users) 32: AuthRepositoryTest 17, GuestImportRepositoryTest 9, LocalUserStoreTest 6 13: AuthScreensTest 6, GuestImportTest 3, AuthenticationFlowTest 2, OnboardingTest 2
Wardrobe analysis and labels 48 (Django, apps.wardrobe, including the label endpoints) 9: MeasurementGeometryTest 23: AppNavigationTest 5, GarmentLandmarksTest 4, WardrobeScreenTest 4, CaptureFilesTest 3, GarmentEditorTest 3, GarmentLabelFlowTest 2, WardrobeColorTest 2
Recommendation and outfit APIs 56 (pytest, tests/recommendation/) + 12 (Django, apps.outfits) 15: OutfitRepositoryTest 6, GarmentLabelsTest 6, CaptureTypeTest 3 6: HomeScreenTest 3, FrontPhotoTest 3
Body analysis 86 (pytest, tests/test_*.py; 3 of them check the service endpoints) 39: RemoteBodyAnalyzerTest 9, BodyMeasurementsTest 8, InsightsTest 7, BodyProfileStoreTest 5, BodyFigureGeometryTest 4, ReferenceAccuracyTest 3, ServerContractTest 3 Body analysis screens are reached through OnboardingTest
Total 142 pytest + 110 Django 95 42

Known failing, skipped or unexecuted tests and reasons:

  • Fixed in PR #30 (bfe69cd), previously failing: OnboardingTest.accountOnboardingSavesPreferencesResumesDraftAndCanSkipOptionalBodyAndClothes looked for a text field labelled 키 (cm), but the label on the screen is 키 (cm) * and the field sits below the fold. The test now uses 키 (cm) * with performScrollTo(); the app was not changed. On b14de4f all 39 non-opt-in device tests pass on the emulator.
  • Fixed in PR #30 (bfe69cd), previously flaky on Windows: apps.users.test_imports.GuestImportTests.test_conflict_can_keep_or_replace_and_changed_version_cannot_overwrite failed in some local runs under coverage (200 != 409). The import version is the row's updated_at timestamp, and on Windows a second save inside the same clock step kept the same version. The test now sets updated_at explicitly one second later, so it no longer depends on clock resolution. The Linux CI runner and the server keep microseconds, so the app itself was not affected.
  • Skipped (device): the three opt-in live tests listed under the device-test command (AuthScreensTest and GuestImportTest live-server tests, GarmentLandmarksTest.localModelAcceptsAnAndroidEncodedFrame). They need a development server, an unused username or a signed-in account, and were not enabled in this run.
  • Skipped (backend, CI only): the MediaPipe model-load smoke test is skipped when the pose model file is absent. CI does not download it; the Backend CI image job loads the same model inside the Docker image instead.
  • External Gemini responses and production MySQL were not tested in the mocked/local suite.
  • The AR measurement screens (ui.wardrobe.capture, 0 % on Android) need ARCore and a real camera, so no automated test covers them. They were checked by hand on a phone.

Results below the coverage targets, reasons and corrective actions:

  • Android ViewModels: 33.9 % / 30.0 % against 60 % / 40 %.
    • Reason: ViewModels are reached only through device UI tests, and four have no test of their own: WardrobeViewModel, GarmentAnalysisViewModel and CodiBookViewModel (0 %), and HomeViewModel (16.9 %). The project also has no coroutine test library yet.
    • Corrective action (Iteration 3): add kotlinx-coroutines-test and JVM unit tests for each ViewModel with fake repositories, written by the owner of each screen, starting with the four above. Re-measure at the end of Iteration 3.
  • The other six components meet their targets.

Conversational outfit editing: test and coverage results (2026-10-22)

The chat tests cover garment locking and unlocking, combined text and direction input, saving a revised outfit, and retrying errors or a locked-item conflict. backend/apps/outfits/test_chat.py also checks account ownership, request validation, model failure, one-edit text keeps, and duplicate-safe saves. frontend/app/src/test/java/com/swpp/stylemate/chat/ChatRepositoryTest.kt checks the Android API contract; frontend/app/src/androidTest/java/com/swpp/stylemate/chat/ChatScreenTest.kt exercises the chat screen on an emulator.

Run Environment and command Result
Backend chat/API coverage Backend CI on 05581e5; run and backend-coverage report Passed
Android JVM unit tests Local JDK 21; ./gradlew --no-daemon -PandroidTestCoverage createAggregatedCoverageReport 100 passed, 0 failed
Android device tests Medium Phone emulator, Android API 37; same command 46 total: 43 passed, 0 failed, 3 opt-in live tests skipped

The Android command combines JVM unit and device-test data in the JaCoCo report at frontend/app/build/reports/aggregated_code_coverage_html_report/global/index.html.

Chat component Lines (C0) Branches (C1) Evidence
Backend chat API (apps/outfits/chat.py) 89.2 % (141/158) 76.6 % (49/64) Backend CI coverage report
Backend text-intent extraction (recommendation/chat_intent.py) 51.6 % (32/62) 38.5 % (10/26) Backend CI coverage report; external model responses are mocked
Android chat repository package 90.3 % (65/72) 50.0 % (12/24) Local JaCoCo merged report
Android chat UI package 66.8 % (243/364) 43.1 % (113/262) Local JaCoCo merged report
ChatViewModel 8.6 % (7/81) 0 % (0/86) Local JaCoCo merged report

The architectural Android targets are compared against the complete local merged report, not the individual chat-package rows:

Android layer Target (C0 / C1) Actual C0 Actual C1 Met
Data/repository 75 % / 50 % 80.9 % (1114/1377) 55.1 % (573/1039) Yes
ViewModels 60 % / 40 % 30.9 % (224/726) 24.6 % (124/504) No
UI 40 % / – 48.4 % (1761/3642) 35.3 % (864/2450) Yes

The ViewModel layer remains below its target. ChatViewModel needs tests for session continuity, locks, undo, retry, and save state; these can be added with a coroutine test dispatcher and a fake chat repository. The four new screen tests cover the visible controls but do not directly exercise those ViewModel branches. Espresso 3.7.0 is used for the local device run because the older transitive version failed before tests started on API 37.

Changes to previously submitted targets, if any: None. These are the first coverage targets of the project.

3. AI Module Testing

To be completed in Iteration 3.

4. Acceptance Testing

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

5. Alpha & Beta Testing

To be completed in Iteration 5.

Clone this wiki locally