# 10. 테스트 계획 ## 1. 원칙 - "될 것 같다"가 아니라 테스트 결과로 완료를 판단한다. - 큰 테스트(부하, 장애 주입, E2E)를 돌리기 전에는 **먼저 Gitea 저장소에 커밋·푸시**하고 진행한다(사용자 요구사항). 결과는 커밋 해시와 함께 기록. - 모든 PR/커밋 전: `bun run typecheck && bun run lint && bun test`. ## 2. 테스트 종류 | 종류 | 도구 | 대상 | 언제 | |---|---|---|---| | 규칙 단위 | `bun test` | `packages/games/*` | 매 커밋 | | 무작위 대국/불변식 | `bun test` + `engine/testing.ts` | 모든 게임(시드 1,000개, CI에서는 200개) | 매 커밋 | | 정보 유출 | 같은 도구 | 숨김 정보 게임 | 매 커밋 | | 서버 통합 | `bun test` + 실제 WS 클라이언트 | 인증, 방 만들기/입장, 행동, 재접속, 강퇴, 한 판 더 | 매 커밋 | | 복구 | 통합 테스트 | 서버 인스턴스 종료 → 같은 DB로 재시작 → 상태 동일 | 매 커밋 | | E2E | Playwright(크로미움 + 모바일 뷰포트) | 게스트 시작 → 방 만들기 → 링크로 두 번째 사용자 입장 → 오목 한 판 끝까지 | 마일스톤마다 | | 접근성 | axe-core(Playwright) | 주요 화면 | 마일스톤마다 | | 성능 | Lighthouse(모바일) | 홈, 방 | 마일스톤마다, 예산 위반 시 실패 | | 부하 | 자체 Bun 스크립트(가짜 클라이언트) | 동시 2,000 연결, 방 500개, 각 방 2초마다 행동 | 마일스톤 M2, M5, 출시 전 | | 장애 주입 | 스크립트 | 게임 중 서버 강제 종료(SIGKILL), 네트워크 끊김, 느린 클라이언트 | 마일스톤 M2, 출시 전 | ## 3. 핵심 통합 시나리오 (M1에서 반드시 통과) 1. 게스트 A가 방 생성 → 코드 6자리 수신 → B가 코드로 입장 → 자동 착석 → A 시작 → 오목 끝까지 → 결과 저장 확인. 2. B가 링크로 입장(로그인 안 됨) → 닉네임 입력 → 자동 착석. 3. 게임 중 B의 WS를 강제로 끊음 → A 화면에 "연결 끊김" → B 재연결 → 같은 상태·같은 차례 수신. 4. 게임 중 서버 프로세스 SIGKILL → 재시작 → A, B 자동 재연결 → 수 이어서 두기 가능, 이전 수 모두 보존. 5. B가 자기 차례가 아닐 때 `act` 전송 → `reject`, 상태 변화 없음. 6. 같은 `cs`로 두 번 전송 → 한 번만 처리. 7. B가 다른 탭으로 접속 → 옛 탭 `bye: replaced`. 8. 턴 시간 초과 → `onTimeout` 행동 적용. 9. 방장이 나감 → 방장 자동 이전. 10. 초당 100개 메시지 전송 → 제한 동작, 서버 정상. 11. 잘못된 JSON / 스키마 위반 / 16KB 초과 메시지 → 오류 응답 또는 연결 종료, 서버 정상. 12. 디스코드 로그인 콜백 state 불일치 → 거절. ## 4. 부하 테스트 합격 기준 - 동시 연결 2,000, 진행 중 방 500개, 초당 행동 250개에서: - 행동 → 상대 수신 p95 < 50ms(같은 머신 기준), p99 < 100ms - 서버 CPU < 70%(4코어 기준), 메모리 < 1GB - 오류 0, 연결 끊김 0 - 결과는 `docs/reports/load-YYYYMMDD.md`에 커밋 해시와 함께 기록. ## 5. 수동 점검표 (마일스톤마다) - [ ] 실제 휴대폰(안드로이드 Chrome, 아이폰 Safari)에서 링크로 들어와 한 판 - [ ] 글자 "아주 크게" 설정에서 모든 화면이 깨지지 않음 - [ ] 다크 모드 - [ ] 와이파이 → LTE 전환 중 게임 이어짐 - [ ] 화면 끄고 1분 뒤 켰을 때 자동 복귀 - [ ] 카카오톡으로 링크 공유 시 미리보기 표시