ship-gis/.claude/rules/testing.md
htlee ac3c204843 refactor: 민간화 + 팀 프로젝트 구조 전환
- 해경 관련 코드/에셋 정리 (KCGV, 해경관할구역 FGB, PatrolShipSelector)
- 위성/기상/퍼블리시/레거시 모듈 전체 삭제
- STOMP WebSocket → AIS Target API HTTP 폴링 방식 전환
- 세션 인증 임시 비활성화 (VITE_DEV_SKIP_AUTH)
- 환경변수 민간 데모용으로 재구성
- 팀 워크플로우 v1.2.0 구조 적용 (.claude/rules, skills, settings)
- .githooks, .editorconfig, .node-version 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 06:13:08 +09:00

2.2 KiB

TypeScript/React 테스트 규칙

테스트 프레임워크

  • Vitest (Vite 프로젝트) 또는 Jest
  • React Testing Library (컴포넌트 테스트)
  • MSW (Mock Service Worker, API 모킹)

테스트 구조

단위 테스트

  • 유틸리티 함수, 커스텀 훅 테스트
  • 외부 의존성 없이 순수 로직 검증
describe('formatDate', () => {
  it('날짜를 YYYY-MM-DD 형식으로 변환한다', () => {
    const result = formatDate(new Date('2026-02-14'));
    expect(result).toBe('2026-02-14');
  });

  it('유효하지 않은 날짜는 빈 문자열을 반환한다', () => {
    const result = formatDate(new Date('invalid'));
    expect(result).toBe('');
  });
});

컴포넌트 테스트

  • React Testing Library 사용
  • 사용자 관점에서 테스트 (구현 세부사항이 아닌 동작 테스트)
  • getByRole, getByText 등 접근성 기반 쿼리 우선
describe('UserCard', () => {
  it('사용자 이름과 이메일을 표시한다', () => {
    render(<UserCard name="홍길동" email="hong@test.com" />);
    expect(screen.getByText('홍길동')).toBeInTheDocument();
    expect(screen.getByText('hong@test.com')).toBeInTheDocument();
  });

  it('편집 버튼 클릭 시 onEdit 콜백을 호출한다', async () => {
    const onEdit = vi.fn();
    render(<UserCard name="홍길동" email="hong@test.com" onEdit={onEdit} />);
    await userEvent.click(screen.getByRole('button', { name: '편집' }));
    expect(onEdit).toHaveBeenCalledOnce();
  });
});

테스트 패턴

  • Arrange-Act-Assert 구조
  • 테스트 설명은 한국어로 작성 (it('사용자 이름을 표시한다'))
  • 하나의 테스트에 하나의 검증

테스트 커버리지

  • 새로 작성하는 유틸리티 함수: 테스트 필수
  • 컴포넌트: 주요 상호작용 테스트 권장
  • API 호출: MSW로 모킹하여 에러/성공 시나리오 테스트

금지 사항

  • 구현 세부사항 테스트 금지 (state 값 직접 확인 등)
  • getByTestId 남용 금지 (접근성 쿼리 우선)
  • 스냅샷 테스트 남용 금지 (변경에 취약)
  • setTimeout으로 비동기 대기 금지 → waitFor, findBy 사용