Repository navigation
Conversation
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 탈퇴 사유 작성 테스트를 기능 단위 한국어 명세 12개로 다시 씀(준비/실행/확인 구역, arguments로 경우 분리, 기대값은 명세 값으로 직접) - 저장소에 넘기기만 하는 UseCase 4개의 테스트 삭제 — Mock 호출만 세면서 토큰 삭제를 확인한 것처럼 보였음. 실제 동작은 AuthData 몫 - 쓰는 곳이 없어진 MockAuthRepository와 .testing 타깃 삭제 - 모듈 주의사항에 UseCase 테스트가 일부러 없다는 것을 기록 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 테스트 5원칙(읽힌다 · 판단하는 코드를 테스트한다 · 버그를 잡는다 · 리팩터링에 깨지지 않는다 · 늘 같다)을 검사하는 규칙 13개 - 파일 단위: test-name · test-assert · test-aaa · test-aaa-act(warning) · test-body-length(warning) · test-arguments · test-determinism · test-result-only · test-double-query - 모듈 단위(Sources↔Tests 교차): test-passthrough · test-required · test-error-case · test-source-constant - TestSpecScope.modules에 든 모듈(현재 AuthDomain)에만 적용 — 재작성을 마친 모듈부터 켠다 - 모듈 루트 TEST_SPEC.md(테스트 목록)를 --write-test-specs로 만들고, 일반 실행은 최신인지 검사(test-spec-file) - 예외 주석 `// archlint:allow <규칙> — 이유` 지원, 이유가 없으면 무시 - 규칙마다 위반·통과 예시 자체 테스트 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- Mutate: 모듈 Sources에 버그를 하나씩 심고(연산자 뒤집기 · ! 삭제 · true↔false · 정수+1 · 문장 삭제) 모듈 테스트를 돌려, 테스트가 못 잡은 버그를 보고 - 넘기기만 하는 UseCase는 ArchLint와 같은 판정으로 변이 대상에서 제외 - Sources가 깨끗할 때만 시작, 변이마다 원본 복구, DerivedData는 레포 밖 임시 폴더 - AuthDomain 실행 결과: 버그 14개 모두 잡힘(컴파일 안 되는 3개 제외) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- TESTING.md: 규칙 목록은 ArchLint README에 두고, 5원칙의 이유 · 무엇을 테스트하고 안 하나 · 작업 순서(목록 합의 → 작성 → ArchLint·TEST_SPEC.md → 뮤테이션) · 사람이 보는 곳 · Stub/Mock · 적용 범위만 적음 - "UseCase 테스트 필수"를 "판단하는 코드는 테스트 필수, 넘기기만 하는 UseCase는 테스트하지 않는다"로 바꿈(CLAUDE.md · Domain 가이드 · WORKFLOW · 완료 점검) - PR 리뷰 agent와 new-module 스킬의 테스트 안내를 새 기준에 맞춤 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 리뷰 초안 테스트 13개로 재작성(기간 정규화·평점·매력 포인트·키워드). 기대값은 소스 상수 대신 명세 숫자로 쓴다 - 넘기기만 하는 UseCase 3개의 테스트와 MockNovelReviewRepository 삭제(UseCase Mock 2개는 Feature가 써서 유지) - ReadingPeriod·Rating 테스트를 코드가 있는 BaseDomain으로 이동(재작성은 BaseDomain 차례에) - 테스트 규칙 적용 범위에 NovelReviewDomain 추가, TEST_SPEC.md 생성 - 뮤테이션 22개 중 20개를 잡았고 생존 2개(평점 대입)는 테스트를 더해 막았다 — 가이드에 "담는 것은 넘기는 것이 아니다" 추가 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 테스트 실패 시 xcodebuild가 시뮬레이터 진단을 모으느라 몇 분씩 멈추던 것을 끔(-collect-test-diagnostics never) - 시뮬레이터를 미리 켜 두고, 도구가 켰으면 끝날 때 끔(실행마다 켰다 끄던 30초 제거) - 출력을 줄 단위로 내보내고 버그마다 걸린 시간을 표시 - NovelReviewDomain 26개 기준 약 1.5시간 → 2분 35초, 결과는 22/22로 같음 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- test-source-constant: 이름만 보던 비교를 "타입.이름"으로 바꿈 - enum case `DeepLink.novelDetail`을 내부 상수 `NotificationView.novelDetail`로 오인하던 오탐 - test-arguments·목록 파일: `[…] as [(Date?, Date?)]`처럼 타입을 붙인 배열도 항목을 읽음 - nil이 섞인 튜플은 타입을 적어야 컴파일된다 - 두 경우 모두 규칙 자체 테스트 추가 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 테스트 81개 → 54개, 스위트 9개(독서 기간·평점·매력 포인트·작성자 프로필 이동·작품 관심 등록·딥링크·앱 리뷰 요청·전체 키워드 불러오기·키워드 검색) - 넘기기만 하는 UseCase(인기 키워드·온보딩 힌트) 테스트와 MockOnboardingHintRepository 삭제 - ReadingPeriod.init에 calendar 인자 추가(기본 .current) — 같은 날 판정을 시간대와 무관하게 테스트 - MockKeywordRepository: 조회 호출 횟수를 세지 않고, 동기화 여부로 답을 바꾸는 Stub으로 변경 - NovelDomain 테스트 2개 파일에서 조회 횟수 확인 4줄 제거 - 앱 리뷰 요청은 저장소 숫자가 아니라 "요청할까?"의 답만 확인, 기준 횟수는 기본값(3번)을 그대로 씀 - TestSpecScope에 BaseDomain 추가, TEST_SPEC.md 생성 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 뮤테이션에서 "id는 1부터" 경계가 살아남음(0은 막는지 봤지만 1을 읽는지는 안 봤다) - 컬렉션 상세 읽기 경우를 id 1로 바꿔 경계를 고정, 버그를 손으로 심어 잡히는 것 확인 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 검색도 조회인데 이름이 search…라 test-double-query가 검사하지 않던 구멍 - 지금 걸리는 코드 없음(MockKeywordRepository는 검색을 기록하지 않게 바뀜) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 넘기기만 하는 UseCase 8개 테스트와 MockCollectionRepository(.testing 타깃) 삭제 - 컬렉션 좋아요 7개·컬렉션 초안 작성 31개로 재작성(78개 → 38개) - 설명 글자 수 제한·남은 글자 수, 작품 목록 100개 경계값 테스트 추가 - 작품 목록을 통째로 바꿀 때도 같은 작품 중복을 duplicatedNovel로 거부 - 테스트 명세 규칙 적용 범위에 CollectionDomain 추가, TEST_SPEC.md 생성 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 스위트 이름을 화면 용어인 "컬렉션 만들기·수정하기"로 변경 - "저장된 값에서 만들기"를 "수정하기 열기" 장면으로 다시 쓰고, 잘라 내는 테스트도 실제 경로(수정하기 열기)를 거치게 변경 - 대표 작품을 "고르다·대표 선택"으로 통일 - 나만 보기 테스트 이름을 구체적으로 변경 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 작품 구역을 "작품 추가·빼기"·"작품 목록 바꾸기"·"작품이 빠질 때 대표"로 나누고, 대표 관련은 "대표 작품" 옆으로 이동 - 목록 바꾸기 테스트 이름을 "새 목록"을 주어로 다시 씀(100개여도 통째로 바꿀 수 있다 등) - 대표로 고르지 않은 작품을 빼는 테스트 이름도 "대표 선택"으로 통일 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- "새 컬렉션은 모두에게 보인다" → "컬렉션을 새로 만들 때 나만 보기는 꺼져 있다"(다음 테스트와 같은 "나만 보기" 단어로) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- test-assert에서 이름의 숫자 검사를 떼어 test-name-number(error)로 분리 - "0.5점 단위"처럼 숫자가 단위를 말할 때 allow 주석으로 빼도 같은 테스트의 != nil 검사는 그대로 남도록 - 규칙 자체 테스트에 allow 주석 경우 추가, README 표 갱신 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- "반 점 단위" → "0.5점 단위"(더 자연스러운 말) - "0.5점 단위가 아니면…"은 0.5가 넣는 값이 아니라 단위라 test-name-number allow 주석으로 이유를 남김 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 넘기기 판정: 결과를 거르거나 이어 부르면(클로저·체이닝) 넘기기로 보지 않는다 - allow 주석: test- 규칙에만 통한다(아키텍처 규칙은 못 끈다) - test-error-case: Entity 폴더 대신 ValidationError 이름으로 찾는다(BaseDomain 포함) - Mutate: 원본을 미리 읽어 Ctrl-C·실패에도 되돌리고, 5분 넘는 버그는 끊는다 - Mutate: Linux 빌드에서 깨질 수 있는 setvbuf(stdout) 제거, Int.max 넘침 방지 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 키워드 검색: 가짜 저장소가 검색어마다 답을 정해 검색어 전달을 결과로 확인 - 독서 기간: 한쪽 날짜만 있을 때 옮기거나 채우는 경우 3개 - 평점: 2.5(0.5점이 붙은 평점) - 리뷰 초안: 평점·기간을 지우는 경우 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- test-error-case: 이름 대신 Error enum 전부를 보고 저장소 에러(RepositoryError·Sources/Repository/)만 뺀다 - test-double-query: 조회 메서드 안 지역 변수로 결과를 만드는 것은 호출 기록으로 보지 않는다 - Mutate: SIGTERM·SIGHUP에도 되돌리고, 끝낼 때 돌던 xcodebuild를 멈춘다 - Mutate: 시간 초과를 실제로 끊었을 때만 세고, 중간 실패 때 시뮬레이터를 정리한다 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- Mutate: 신호로 멈춘 뒤 뜬 xcodebuild도 바로 멈추고, 정상 종료를 시간 초과보다 먼저 본다 - Mutate: 원본으로 되돌리지 못한 파일을 숨기지 않고 알린다 - test-double-query: 클로저 매개변수·$0·`_ =`은 호출 기록으로 보지 않는다 - test-error-case: LocalizedError처럼 Error가 들어간 채택도 에러 enum으로 본다 - 문서: kill(-9 제외) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
테스트 커버리지 리포트
Generated by CI on 2026-10-16 18:16 KST |
Collaborator
Author
|
MARK -> SUITE 로 구분 기준 변경 & SUITE내에 SUITE를 넣어서 테스트 그룹 사이의 관계를 더 명확히 표현. |
- 하위 @suite를 부모 제목 아래 한 단계 내린 제목(###)으로 적는다 - 파일 경로는 맨 위 스위트에만 적고, 테스트 없는 스위트는 뺀다 - 목록 파일 생성 자체 테스트 2개 추가 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- CollectionDraft 테스트 31개를 제출·이름·설명·작품·대표 작품 등 9개 하위 Suite로 묶는다 - 준비 함수는 하위 Suite에서 부를 수 있게 파일 아래 private 함수로 옮긴다 - TESTING.md에 하위 Suite를 쓰는 기준을 적는다 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- DeepLink 테스트 16개를 링크 만들기·링크 읽기·카카오톡 링크 읽기·푸시 알림 읽기로 묶는다 - NovelReviewDraft 테스트 15개를 기간·평점·매력 포인트·키워드로 묶는다 - 기간 테스트만 쓰는 고정 날짜는 기간 Suite 안으로 옮긴다 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- WithdrawalReasonDraft 테스트를 항목 고르기·탈퇴 이유 작성·제출로 묶고, 처음 상태 테스트는 부모에 둔다 - ReadingPeriod 테스트를 만들기·독서 상태에 맞추기로 묶고, 고정 날짜와 서울 달력은 파일 위 private 상수로 옮긴다 - TESTING.md에 고정 값 위치와 부모에 두는 테스트 기준을 더한다 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
- 기준은 개념(사용자 동작·규칙 덩어리)이고, 1개짜리 하위 Suite도 허용한다 - 10개쯤은 나눌지 따져 보는 신호로만 쓰고 ArchLint로 강제하지 않는다 - 테스트 목록 합의 단계에서 하위 Suite 묶음도 사람이 승인한다 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
💡 Issue
💭 Summary
AI가 코드를 쓰고 리뷰까지 하면서, 사람이 구현 코드를 다 읽는 게 병목이 됐어요.
그래서 사람은 테스트를 보고 믿을 수 있게 만들었어요.
Domain 4개 모듈(Auth·NovelReview·BaseDomain·Collection)의 테스트를 "읽히는 기능 명세"로 다시 썼어요.
그리고 그 테스트가 믿을 만한지 기계가 검사하게 했어요.
🔑 Key Changes
1. 테스트를 기능 명세로 재작성
.testing타깃과 Mock도 지웠어요.@Suite로 나눴어요.TEST_SPEC.md)에도 부모 아래 소제목(###)으로 나와요.docs/TESTING.md).@Test): 186개 → 123개2. ArchLint 테스트 명세 규칙 (
Tooling/ArchLint)Architecture Rulesjob에서 돌아요.!= nil만 확인하기 금지,Date()·Calendar.current금지, 넘기기만 하는 UseCase 테스트 금지// archlint:allow <규칙> — 이유주석을 달아요.TestSpecScope.modules).3. 테스트 목록 파일 (
TEST_SPEC.md)4. 뮤테이션 도구 (
Mutate)<를<=로 바꾸기, 문장 하나 지우기swift run --package-path Tooling/ArchLint Mutate <모듈>5. 소스 변경 (3곳)
CollectionDraft.setNovels: 같은 작품이 두 번 들어오면duplicatedNovel로 거부해요.addNovel만 막아서 들어오는 길마다 규칙이 달랐어요.ReadingPeriod:calendar인자를 추가했어요(기본값 있음). 테스트가 기기 시간대와 상관없이 같은 결과를 내게 하려고요.MockKeywordRepository: 몇 번 불렀는지 대신 "동기화했는지"와 "검색어"에 따라 답을 바꿔요.6. 문서
docs/TESTING.md를 "테스트가 지켜야 할 5가지" 중심으로 다시 썼어요.CLAUDE.md,WORKFLOW.md,DEFINITION_OF_DONE.md,wss-pr-reviewer,new-module스킬도 맞췄어요.📱 Simulation
해당 없음(테스트·도구·문서 변경이에요).
🧑🧒🧒 To Reviewer
어디부터 읽으면 좋은지
TEST_SPEC.md: 빠진 규칙이 없는지, 원하는 동작인지 봐 주세요.RatingTests.swift의 "0.5점 단위"(숫자가 넣는 값이 아니라 단위를 말해요)측정 결과
옛 테스트에 지금 규칙을 돌려 봤어요(develop 기준).
!= nil만 확인: 14Calendar.current에 기댐: 4test-source-constant).뮤테이션(심은 버그 중 테스트가 잡은 수):
리뷰에서 나온 것
wss-pr-reviewer와 Codex로 3라운드 리뷰했어요. 고친 내용은 마지막 커밋 6개([Fix]·[Test]·[Docs])에 있어요.wss-pr-reviewer는 🔴 0 🟡 0이었어요.알고 있는 한계
확인 부탁
swift:6.3.3컨테이너)에서 빌드되는지는 이 PR의Architecture Rules결과로 처음 확인해요.※ Reference
docs/TESTING.md: 테스트가 지켜야 할 5가지, 작업 순서, 사람이 보는 곳Tooling/ArchLint/README.md: 규칙 목록과 뮤테이션 도구🤖 Generated with Claude Code
https://claude.ai/code/session_015vk4VehJFcSyPXzh7syk9V