Files
homeclaw/tests
kimandClaude Code eb516e2b74 feat: 작업실 저장 개편 — 전체문서 PUT을 프로젝트 단위 PUT으로 + LOW 2건
저장 개편(리뷰 #4 근본치료):
- PUT /api/workshop/project/:id — 서버가 디스크의 현재 문서에 해당 프로젝트만
  upsert. 대시보드 저장과 채팅 도구 저장이 겹쳐도 서로 다른 프로젝트 편집이
  통째로 사라지지 않음. DELETE /api/workshop/project/:id,
  PUT /api/workshop/active(포인터 단독) 신설. 옛 전체문서 PUT은 스테일 탭
  호환으로 유지
- 클라이언트: dirtyProjects 추적 → saveProject는 바뀐 프로젝트만 순차 PUT,
  활성 포인터는 putActive() 즉시 저장, 프로젝트 삭제는 DELETE 직접 호출,
  beforeunload flush도 프로젝트 단위 keepalive PUT으로 전환
- upsertProject/removeProject를 순수함수로 추출, 단위테스트 4건

LOW 2건:
- loadFiles에 요청 일련번호 — 빠른 프로젝트 전환 시 옛 응답이 나중에 도착해
  이전 프로젝트 파일을 새 판에 그리는 레이스 제거
- 슬라이서 인계 ?load=를 JSON 배열 인코딩으로 전환(파일명에 쉼표 있으면
  옛 쉼표 join이 깨지던 문제). 슬라이서 쪽은 JSON 우선, 옛 형식 폴백 유지

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-24 07:38:53 +09:00
..

tests/

npm test          # 전체 실행 (약 0.6초)
npm run test:watch  # 파일 저장할 때마다 재실행
npx tsx --test tests/prompt-gates.test.ts   # 한 파일만

Node 22 내장 러너(node:test) + tsx. 테스트 프레임워크 의존성 없음 — jest/vitest 설치 불필요.

배경

2026-07-29 기준 이 디렉터리는 비어 있었고, package.json의 test 스크립트는 존재하지 않는 tests/test-v2.ts를, gateway 스크립트는 v4.3.5에서 삭제된 src/gateway/server-v2.ts를 가리킨 채 방치돼 있었다. 즉 npm test가 실행 자체가 안 되는 상태로 몇 달을 보냈다.

그 대가는 명확했다. 같은 날 프롬프트 게이트 정규식을 다섯 번 고치면서, 매번 node -e "..."로 임시 검증 스크립트를 손으로 짜고 버렸다. 회귀 방지는 하나도 남지 않았다.

무엇을 테스트하는가

순수 함수 우선. 이 저장소에서 가장 값어치 있는 테스트 대상은 I/O가 없는 판정 함수들이다:

파일 대상 왜 중요한가
prompt-gates.test.ts src/gateway/guards/prompt-gates.ts 모델 동작을 강제/억제하는 정규식 게이트. 각 함수는 전부 실제 프로덕션 사고를 겪고 생겼다
usage-log.test.ts src/providers/usage-log.ts Ollama 외 모든 provider의 토큰 집계 단일 지점

이 함수들의 회귀는 크래시도 스택트레이스도 없이 조용히 구멍을 다시 연다. 예를 들어 looksLikeUnverifiedSpecClaim이 한 패턴을 놓치면, 모델이 지어낸 수치가 검증 없이 그대로 사용자에게 간다 — 로그에는 아무 이상도 남지 않는다.

케이스 작성 규칙

프로덕션 원문을 그대로 쓸 것. 줄이거나 다듬지 말 것.

[2026-07-29] 태그가 붙은 케이스들은 실제 대화 로그에서 가져온 문장이다. 어색한 표현이 바로 핵심이다 — 정규식이 놓치는 건 언제나 "예상하지 못한 말투"이지 교과서적인 문장이 아니다.

이 규칙은 실제로 값을 했다. 위 테스트를 처음 쓸 때 원문 "...GPU 간 통신 병목으로 인해 토큰 처리 속도 손실이 약 15%~25%..."를 "...토큰 처리 속도 손실이 약 15%~25%..."로 줄여 썼더니 테스트가 실패했고, 그게 진짜 버그였다. 원문에 우연히 들어있던 GPU 덕에 걸리던 것이지, 같은 주장을 한 단어 다르게 쓰면 그대로 통과하고 있었다. (→ SPEC_CONTEXT_KEYWORD에 토큰/대역폭/추론/처리속도 추가)

다음에 추가하면 좋을 것

현재 커버리지는 순수 함수에 한정된다. 아래는 값어치는 크지만 먼저 리팩터링이 필요하다:

  • skillToolFilter (handle-chat.ts) — 도구 노출을 결정하는 키워드 게이트. handleChat() 내부 클로저라 지금은 테스트 불가. 순수 함수로 추출하면 바로 테스트 가능해진다.
  • 시스템 프롬프트 조립 — 도구 유무에 따른 조건부 블록(imageEditRuleBlock 등). 역시 handleChat() 내부에 있다.
  • executeWebSearch provider 폴백 체인 — I/O가 있어 mock 서버가 필요하다.

handleChat()은 단일 함수가 2,959줄이라 위 둘 다 막혀 있다. 그 분해가 테스트 커버리지를 넓히는 가장 큰 지렛대다.