Repository navigation
repository fake 59벌을 계약 옆 testFixtures 17벌로 — 계약 1건에 수정 지점 최대 7곳인 구조 제거 (총괄) #1030
Description
총괄 이슈다. 실제 작업은 도메인 모듈별 서브이슈에서 하고, 여기서는 규약과 진행만 본다.
배경
repository fake 가 테스트 소스셋 전체에 59개 흩어져 있는데, 서로 다른 인터페이스는 17종뿐이다. 59개 중 58개가 "같은 인터페이스를 2벌 이상 구현한" 무리에 속한다. (집계: origin/develop af3f4610, src/test·src/androidTest 의 .kt 98개 스캔)
문제는 중복 자체가 아니라 수정 지점이 갈라져 있다는 것
계약을 하나 바꾸면 fake 를 N 곳 고쳐야 하는데, 그 N 곳이 서로 다른 컴파일 단위에 있다. 작성자는 자기 PR 이 초록인 걸 보고 "다 고쳤다" 고 믿지만, 실제로는 자기 모듈 안의 몇 벌만 고친 것이다.
#911 이 DailyQuestionRepository.create/update 를 Result<Long> 으로 바꿨을 때가 그대로다 — 모듈 유닛 테스트 쪽 fake 는 같은 PR 에서 깨져 고쳐졌고, app/src/androidTest 쪽 2벌은 아무 신호 없이 남아 #1022 의 6건이 됐다. #888(유닛 테스트 fake 잔재 2건)도 같은 계열이다.
#949 가 세운 :app:compileDebugAndroidTestKotlin 게이트는 이 파손을 PR 에서 보이게 만들었지만, "고칠 곳이 6곳" 이라는 사실 자체는 그대로다. 계약 하나에 6곳을 손으로 맞추는 구조가 남아 있는 한 게이트는 재고를 알려줄 뿐 재고가 쌓이는 걸 막지 못한다.
해법 — fake 를 계약 옆으로
testFixtures 로 도메인 모듈이 자기 인터페이스의 fake 를 함께 내보내고, 유닛 테스트와 androidTest 가 그걸 가져다 쓴다. 규약 플러그인(AndroidDomainConventionPlugin)에 testFixtures.enable = true 한 줄이면 도메인 모듈 전체가 대상이 된다.
이게 고치는 것: 계약을 바꾸면 같은 모듈의 compileDebugTestFixturesKotlin 이 그 자리에서 깨진다. 작성자가 자기 PR 에서, 자기가 연 파일 옆에서 본다. androidTest 가 남의 모듈이라 안 보이던 문제가 구조적으로 사라진다. (#1045 에서 실측 확인)
픽스처 규약 (정본)
- 기본 동작은 메모리 저장소 — 생성하면 쌓이고 수정·삭제가 반영되며 조회는 계약대로 거른다. 호출은 전부 기록해 테스트가 사후에 단언한다.
- 저장소 동작으로 표현 못 하는 시나리오(경합용
CompletableDeferred게이트, 스크립트된 실패)는onX람다로 갈아끼운다. - "이 시나리오에서 호출되면 안 됨" 은
strict()+unexpectedCall(...)로 옮긴다 — 기본 동작이 관대해져 종전 fake 가error(...)로 지키던 경계가 사라지지 않게 한다. - 스크립트 큐는 픽스처에 넣지 않는다. 호출부에서
ArrayDeque를 들고onX로 물린다. - 단언 자체는 바꾸지 않는다. 기록 접근자 이름이 달라지는 것까지만 허용하고, 의미가 바뀌어야 한다면 별건으로 분리한다.
진행
서브이슈는 도메인 모듈로 갈랐다. app/src/androidTest 의 같은 파일에 여러 배치의 fake 가 함께 있어 순차로 간다 — blocked_by 로 순서를 걸어 뒀다.
| 순서 | 서브이슈 | 모듈 | 규모 |
|---|---|---|---|
| 1 | #1045 | feature/mindrecord/domain |
4종 16벌 → 4벌 |
| 2 | #1041 | core/domain |
4종 17벌 → 4벌 |
| 3 | #1042 | feature/receiver/domain |
4종 15벌 → 4벌 |
| 4 | #1043 | feature/timeletter/domain |
3종 10벌 → 3벌 |
| 5 | #1044 | feature/afternote/domain |
1종 3벌 → 1벌 |
1벌뿐인 AccountRepository 는 접을 것이 없어 대상이 아니다.
완료 조건
서브이슈가 모두 닫히면 이 이슈를 닫는다. 그 시점에:
- repository fake 가 인터페이스당 1벌(+시나리오 파라미터)로 접혀 있다.
- 도메인 인터페이스에 메서드를 추가하면 그 모듈의
compileDebugTestFixturesKotlin이 실패한다.
비범위
- GMD 스위트를 PR 필수 체크로 올리는 것 — Gradle Managed Device 기반 전 범위 androidTest 인프라와 app·core·onboarding canary 도입 #835 의 "3회 연속 성공 후 판단" 게이트 소관이다.
- 의미 드리프트(컴파일은 되는데 단언이 낡는 것). 에뮬레이터가 필요 없는 androidTest 14개를 feature 모듈 src/test 로 — 위치 때문에 한 번도 실행되지 않는 상태 해소 #1035 가 다룬다.
- fake 를 mock 라이브러리로 대체하는 것.
근거
- Gradle Java Test Fixtures: https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures
- AGP
testFixtures: https://developer.android.com/build/publish-library/configure-pub-variants#test-fixtures
Activity
[-]test: repository fake 59개를 계약 옆 testFixtures 로 접는다 — 계약 1건에 수정 지점 최대 7곳인 구조 제거[/-][+]test: repository fake 59벌을 계약 옆 testFixtures 17벌로 — 계약 1건에 수정 지점 최대 7곳인 구조 제거 (총괄)[/+][-]test: repository fake 59벌을 계약 옆 testFixtures 17벌로 — 계약 1건에 수정 지점 최대 7곳인 구조 제거 (총괄)[/-][+]repository fake 59벌을 계약 옆 testFixtures 17벌로 — 계약 1건에 수정 지점 최대 7곳인 구조 제거 (총괄)[/+]OnlyReadOneBook commentedon Aug 29, 2026
완료 — 서브이슈 전량 종료, 완료 조건 둘 다 충족 (2026-08-29
origin/develop 7345e7ad0실측)서브이슈 5건이 모두
COMPLETED로 닫혔다: #1045(mindrecord) · #1041(core) · #1042(receiver) · #1043(timeletter) · #1044(afternote).완료 조건 1 — fake 가 인터페이스당 1벌로 접혔다
src/testFixtures보유 모듈:core/domain·core/ui·feature/{afternote,mindrecord,receiver,timeletter}/domainsrc/test·src/androidTest에 남은Fake*.kt5건은 전부 대상이 아니다 — 4건은 픽스처 자체를 검증하는 테스트(FakeCoreRepositoriesTest·FakeAfternoteRepositoryTest·FakeReceiverRepositoriesTest·FakeTimeLetterRepositoryTest), 1건은 repository 가 아닌core/network의FakeInterceptorChain문제의 진원이던
app/src/androidTest/.../test/TestFakes.kt는 자체 Repository 구현이 0건이다. 지금은core.domain.testing.FakeAuthRepository·FakeUserRepository를 import 해strict()위에 app 전용 허용 범위만 얹는 87줄짜리 조립 헬퍼다. 「계약 1건에 수정 지점 최대 7곳」의 구조가 사라졌다.완료 조건 2 — 계약을 바꾸면 그 모듈에서 깨진다
강제 장치가 양쪽 규약에 모두 박혀 있다.
AndroidDomainConventionPlugin—extensions.configure<LibraryExtension> { testFixtures { enable = true } }(주석에 이 이슈 번호 명시)JvmDomainConventionPlugin—pluginManager.apply("java-test-fixtures")도메인 모듈이 어느 규약을 타든 계약 옆
testFixtures가 함께 컴파일된다.#1151실측으로 mindrecord·receiver·timeletter 를 JVM 규약으로 옮겨 봤을 때도compileTestFixturesKotlin이 그대로 통과해, 이 구조가 규약 전환을 견디는 것까지 확인됐다.비범위였던 것
더 추적할 것이 없어 닫는다.
test(app): 주간 리포트 fake 를 정본 strict 판으로 되돌린다