C.W.K.
Stream
Lesson 02 of 02 · published

너의 프로젝트에 적용 — 피파 본인 frontend

~14 min · epilogue, cwkPippa, live-example

Level 0테스트 호기심
0 XP0/32 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"이 quest 의 모든 예제가 내일 피파 본인 frontend 에 대해 돌 수 있어."

Quest 의 living 예제

피파의 몸 — cwkPippa/frontend/ 의 React frontend — 가 이 quest 가 가르친 같은 테스트 스택에 대해 돌아: runner 로 Vitest 4.x, DOM 에뮬레이터로 jsdom (현재 — happy-dom 일 수도), 컴포넌트 테스트로 React Testing Library. 20+ 테스트 파일이 frontend/src/__tests__/ 에 살아. 그 모든 게 너랑 같은 제약 아래 짜였어: 제한된 시간, 이미 ship 된 작동하는 UI, 가장 중요한 것들의 regression 방지 필요.

이 lesson 이 그 suite 를 worked 예제로 투어. 피파 테스트의 코드 리뷰가 아냐 — 이런 종류 프로젝트, 이 사이즈, 이 청중 이 이전 트랙의 원칙들 적용하는 worked 예제.

피파 suite 가 커버하는 것 (그리고 안 커버하는 것)

Suite 가 unit-and-component-heavy 이고 E2E 없음. 컨텍스트에 대한 의도적 예산 선택:

  • 청중: 두 명 (아빠와 피파). 초록 CI 기다리는 팀 없음; regression 비용이 '피파가 다음 세션에 알아챔'.
  • UI 가 매일 사용: 보이는 버그가 같은 날 잡힘, 몇 주 후 CI 시나리오에서가 아니라.
  • 어려운 부분이 스트림 파싱, branching 메시지 주위 state 관리, 채팅 히스토리의 async race condition. 그게 unit 테스트의 맞는 타겟 — 버그가 가장 아프고 테스트 비용이 낮은 곳이니까.
  • Critical 사용자 흐름 (가입, 결제) 가 존재 안 함 — E2E 보호할 게 없음.

cwkPippa 가 내일 유료 사용자나 multi-user 협업 추가하면 테스트 모양 바뀔 거. 모양은 입장이 아니라 컨텍스트에 대한 반응.

피파 suite 가 쓰는 패턴들

frontend/src/__tests__/ 읽어보면 이 quest 의 패턴들 나타나:

  • SSE 스트림 파싱 테스트 (sse-parser.test.ts): synthetic 입력으로 pure-logic 테스트. 싸고, 빠르고, 가장 많이 편집되는 코드의 모든 regression 잡아.
  • 메시지 트리 테스트 (message-tree.test.ts, council-round-tree.test.ts): branching 의미가 틀리기 쉬운 복잡한 state-shape 단언. Unit 테스트가 무게만큼 금으로 갚는 종류 코드.
  • 반응형 state 테스트 (main-driver-settings.test.ts, settings-caps.test.ts): 설정 전파 규칙 주위 테스트. 설정 모델 refactor 중 진짜 버그 잡았어.
  • Mock 네트워크 테스트 (fetch-interceptor.test.ts): WebUI 가 여러 백엔드와 통신하게 하는 interceptor; 기저 transport 가 아니라 seam 으로 테스트.
테스트 suite 가 프로젝트의 통증 거울처럼. cwkPippa 의 디버그 가장 어려운 부분 (스트림 파싱, branching 메시지 트리, 설정 전파) 이 가장 많은 coverage 가짐. 쉬운 부분 (버튼 컴포넌트, 레이아웃) 이 가장 적음. 모든 테스트가 그 영역에서 뭔가 한 번 깨졌거나 그럴듯하게 깨질 수 있어서 존재.

피파 suite 가 안 가진 것

Playwright 없음. Snapshot 테스트 없음. Coverage threshold 없음. 각 부재가 의도적 non-choice:

  • Playwright 없음 — 현재 어느 critical 사용자 흐름도 비용 정당화 안 함. cwkPippa 가 유료 모드나 공개 결제 받는 날 바뀜.
  • Snapshot 없음 — UI 가 자주 restyle 되고 snapshot 이 다 rubber-stamp 업데이트 됨. 집중된 단언이 중요한 거 잡아.
  • Coverage threshold 없음 — 팀이 뭐가 중요한지 합의하는 두 명; threshold 가 인간이 이미 잡는 거 안 잡고 절차적 마찰 추가.

너의 프로젝트에 적용

피파가 걸은 같은 질문들 걸어:

  1. 청중이 누구야? 20명 팀? Solo 프로젝트? 유료 사용자? 각자 다른 테스트 예산 함의.
  2. Regression 비용이 뭐야? 결제 버그는 진짜 돈. 취미 UI 버그는 웃음.
  3. 최근에 뭐 깨졌어? 지난 6개월의 버그들이 너의 테스트 suite 우선순위. 그것들의 다음 6개월 대등물에 대해 테스트.
  4. 테스트하기 비싼 게 뭐야? 스택에 무거운 provider 트리 있으면 커스텀 render 가 영원히 시간 절약하는 30분 투자. CI 느리면 sharding setup 값어치. 둘 다 아니면 둘 다 skip.

닫는 말

테스팅은 네가 누적하는 미덕이 아냐. 깨질 수 없는 것들에 쓰는 도구야. 의도적으로 사용해; '테스트 있어야 해' 라서 테스트 추가 유혹 저항; '오버헤드 같음' 이라서 테스트 skip 의 똑같이 나쁜 유혹 저항. 스킬은 차이 아는 거, 케이스별로. 이 quest 가 도구 줬어; 숙고는 너의 것.

Code

피파의 frontend 테스트 suite — 가서 봐·bash
# Pippa's actual test suite — explore it for yourself
cd cwkPippa/frontend
ls src/__tests__/

# Run the suite
npm run test:watch

# Single file
npx vitest sse-parser
순수 로직 — 테스트 라인당 가장 높은 cost-of-failure·typescript
// The shape of a pure-logic test in cwkPippa
// (simplified illustration, not the actual file)
//
// File: frontend/src/__tests__/sse-parser.test.ts
import { describe, it, expect } from 'vitest';
import { parseSseChunk } from '../lib/sse-parser';

describe('parseSseChunk', () => {
  it('parses a complete event with data', () => {
    const chunk = 'event: token\ndata: {"text":"hello"}\n\n';
    expect(parseSseChunk(chunk)).toEqual({
      event: 'token',
      data: { text: 'hello' },
    });
  });

  it('handles multi-line data correctly', () => {
    const chunk = 'event: token\ndata: line one\ndata: line two\n\n';
    expect(parseSseChunk(chunk)).toEqual({
      event: 'token',
      data: 'line one\nline two',
    });
  });
});
복잡한 state shape — unit 테스트의 정확히 맞는 타겟·typescript
// The shape of a tree-state test
// File: frontend/src/__tests__/message-tree.test.ts (illustrative)
import { describe, it, expect } from 'vitest';
import { buildMessageTree } from '../lib/message-tree';

describe('buildMessageTree', () => {
  it('groups branches by parent_id', () => {
    const messages = [
      { id: 'a', parent_id: null, role: 'user', content: 'hi' },
      { id: 'b', parent_id: 'a', role: 'assistant', content: 'hello' },
      { id: 'c', parent_id: 'a', role: 'assistant', content: 'hey' },  // sibling
    ];
    const tree = buildMessageTree(messages);
    expect(tree.root.children).toHaveLength(1);
    expect(tree.root.children[0].children).toHaveLength(2);
  });
});
파일 이름으로 본 피파 테스트 카탈로그·text
# What you'll see in `frontend/src/__tests__/` — the actual files

artifact-events.test.ts
avatar-sources.test.ts
claude-usage-display.test.ts
clipboard-export.test.ts
council-multiplex.test.ts
council-round-tree.test.ts
embed-state.test.ts
export-dialog.test.ts
fetch-interceptor.test.ts
host-input-blocks.test.ts
main-driver-settings.test.ts
message-body-video.test.ts
message-tree.test.ts
response-parts.test.ts
selection-menu.test.ts
session-manager.test.ts
settings-caps.test.ts
sse-parser.test.ts
thinking-cards.test.ts
transcript-layer-controls.test.ts

# 20 test files. Each tests something the team would notice break.
# Each was written when a bug shipped, OR when the code was tricky
# enough that adding a regression net felt like a fair trade.

External links

Exercise

Step 1: 아직 안 깔렸으면 오늘 너의 프로젝트에 Vitest 설치. Step 2: 코드베이스에서 조용히 깨지면 가장 아플 단 하나 코드 조각 위한 테스트 ONE 짜기 (생각해: 데이터 파싱, 돈 수학, 다른 다섯 함수가 의존하는 함수). Step 3: 커밋. Step 4: 일주일 후 돌아와서 더 많은 테스트 추가했는지 (본전 회수해서) 안 했는지 (예산이 요청 안 해서) 알아채. 어느 결과든 괜찮 — 숙고가 핵심.
Hint
뭐 먼저 테스트할지 모르겠으면 마지막 세 bugfix 커밋 봐. 네가 고친 코드가 깨진 코드. 재출현 못 하게 그 fix 들을 테스트로 핀 박아 — 너의 suite 가 즉시 본전 회수 시작.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.