Vitest 는 두 coverage provider 지원: v8 (V8 엔진 native) 와 istanbul (소스 instrumentation). v8 가 default 고 보통 맞는 선택 — 더 빠르고 (소스 재작성 없음), ESM/async 코드에 더 정확하고, TypeScript / Vite 플러그인 춤 없이 작동. Istanbul 은 특정 instrumentation 기능 (예: 여러 런타임 걸친 coverage 병합) 필요할 때만.
설치: npm install -D @vitest/coverage-v8. 그 다음 config 나 CLI 로 활성화: npx vitest run --coverage.
다섯 아니라 네 숫자
Coverage 리포트가 네 퍼센트 보여줘:
Statements: 실행 가능 statement 의 어느 비율이 돌았는지.
Branches: 조건 branch (if/else, ternary) 의 어느 비율이 돌았는지.
Functions: 함수의 어느 비율이 호출됐는지.
Lines: 라인의 어느 비율이 돌았는지 (statements 와 비슷하지만 라인 단위).
Branches 가 가장 정보적. 높은 statement % 와 낮은 branch % 는 테스트가 happy path 만 치고 에러/edge branch skip 한다는 뜻. Branch 숫자가 보통 버그가 숨어있는 곳.
Coverage 가 측정하지 않는 것
Coverage 는 단언 품질 측정 안 해. 함수 호출하고 아무것도 단언 안 하는 테스트가 서른 개 단언하는 테스트와 같이 카운트. it('does the thing', () => { doTheThing(); }) 는 그 함수에 대해 full coverage 이고 zero 검증. Coverage 는 안 테스트된 코드 path 찾기에 써, 테스트된 코드가 맞다 주장에 쓰지 마.
Coverage 는 또 테스트 suite 유용성 측정 안 해. 실제로 ship 하는 버그를 못 잡는 100% coverage suite 가 잡는 60% suite 보다 나빠. 숫자는 도구지 목표가 아냐.
Coverage 는 진단이지 타겟이 아냐. 'Q3 까지 90% coverage 달성' 은 망한 목표 — 팀이 단언 없는 테스트 짜거나 어려운 파일 제외해서 달성. 유용한 목표는 '모든 critical path 가 최소 한 테스트 가짐' — coverage 가 뭐가 빠졌는지 찾는 거 도와, 뭐가 충분한지가 아니라.
Threshold — 천장 말고 바닥으로
vitest.config 에 coverage.thresholds 설정해서 coverage 가 숫자 아래로 떨어지면 run 실패시킬 수 있어. 맞는 사용법: 현재 실제 coverage 와 매칭되는 바닥으로 설정, 진짜 개선 일어날 때만 ratchet up. 잘못된 사용법: 40% coverage suite 에 80% 전체 설정하고 팀이 그걸 game 하는 거 보기.
카운트하면 안 되는 코드 제외
일부 파일은 진짜로 coverage 에 기여하면 안 돼: 타입 전용 파일, 생성된 코드, dev 전용 유틸, 테스트 파일 자체. coverage.exclude 설정해서 빼 — 노이즈 사라지면 퍼센트가 더 의미 있어져.
Code
설치 + coverage 로 실행·bash
# Install the v8 provider
npm install -D @vitest/coverage-v8
# Run with coverage
npx vitest run --coverage
# Coverage UI (alongside the regular vitest UI)
npx vitest --coverage --ui
프로젝트에 coverage 활성화 (@vitest/coverage-v8 + config 블록). npx vitest run --coverage 돌리고 생성된 coverage/index.html 열어. 가장 LOW branch coverage 파일 골라 — 열고, 안 테스트된 branch 하나 찾고, 그것 위한 테스트 추가. 다시 돌려서 숫자 올라가는 거 봐. 그 다음 그 파일의 현재 coverage 에 per-file threshold 설정해서 regression 안 되게 해.
Hint
파일이 0% coverage 보이면, 실제로 테스트가 도달하는 뭔가가 import 하는지 확인. 죽은 코드가 0% 로 보여 — 그건 테스트 짜라는 힌트 아니라 파일 지우라는 힌트.
Progress
Progress is local-only — sign in to sync across devices.