~15 min · vitest-setup, watch-mode, ui-mode, filtering
Level 0테스트 호기심
0 XP0/32 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"save 마다 다시 도는 테스트는 피드백 루프와 의식 사이의 차이야."
Watch 모드가 default
그냥 vitest (인자 없음) 는 watch 모드로 시작해. 관련 테스트 한 번 돌리고 파일 변경 듣고 앉아있어. 파일 save 하면 Vitest 가 변경에 의존하는 테스트만 (import graph 통해) 골라 다시 돌려. 전체 suite 는 네가 요청할 때까지 차가운 상태야.
왜 중요하냐면: 200 개 unit 테스트가 각 30 밀리초면 총 6초야. 매 save 마다 전체 돌리는 것도 괜찮아. 근데 Vitest 의 똑똑한 re-run 은 보통 200-500 밀리초에 끝나 — 테스트가 돌고 있는 걸 잊을 정도로 빠르지. 루프가 이렇게 돼: 코드 바꾸고, 터미널 흘끔, 결과 보고, 반복.
실제로 쓰는 watch 모드 키
Watch 모드 돌아가는 동안 단일 키 단축키로 터미널 안 떠나고 필터링하고 다시 돌릴 수 있어:
a — 전체 테스트 다시 (full pass 강제)
f — 실패한 테스트만 다시 (regression 추적할 때 달콤해)
p — 파일명 패턴 필터 (live regex)
t — 테스트명 패턴 필터
q — 종료
r — 수동 전체 re-run
외울 필요 없어. h 누르면 Vitest 가 도움말 메뉴 출력해줘. 일상에서 쓰는 건 두 개 — p (한 파일로 파고들기) 와 f (실패 추적).
Watch 는 한 터미널, dev 서버는 다른 터미널. 한 곳에서 다중화하지 마 — 페인으로 쪼개야 실패 출력이 읽기 좋아. tmux 나 IDE 의 split terminal 이 해줘. 세팅에 쓰는 몇 초는 실제 변경에서 테스트가 처음 실패할 때 바로 회수돼.
CI 모드 — `vitest run`
vitest run 은 suite 한 번 돌리고 실패 시 non-zero 코드로 종료해. 이게 CI 모양 — watching 없음, UI 없음, 인터랙티브 컨트롤 없음. 출력은 log aggregation 에 적합한 plain text. 대부분 프로젝트는 둘 다 있어: 로컬은 npm test 가 vitest (watch), 파이프라인은 npm run test:ci 가 vitest run --reporter=verbose.
UI 모드 — 브라우저 대시보드
vitest --ui 는 watch 모드 runner 옆에 로컬 web UI 를 열어. UI 는 전체 테스트 트리, 마지막 실패와 그 diff 를 인라인으로 노출, 파일별 re-run 버튼, coverage 켰으면 소스 파일 위에 오버레이까지 보여줘. UI 가 가장 유용한 두 가지: flake 사냥 (실행 이력 시각화) 와 coverage gap 리뷰 (소스 오버레이가 터미널 coverage 보고서보다 읽기 쉬워).
터미널 대체가 아냐 — inner loop 는 터미널이 더 빨라. 근데 뭔가 이상할 때 (로컬에선 통과, CI 에선 실패) UI 의 history 가 발산을 가시화해줘.
필터링이 디버깅이야. 단일 테스트가 실패하면 suite 전체 다시 돌리지 마 — 그 파일로 필터 (p + 파일명), 밀리초 사이클 돌아가게 두고, 고치고, 초록 봐. 가지고 있는 가장 빠른 디버그 루프는 테스트가 1초 미만에 도는 거야.
Code
세 모드 — watch, run, UI·bash
# Local — watch mode (default)
npm test
# or equivalently:
npx vitest
# CI — run once and exit
npm run test:ci
# or:
npx vitest run
# Open the browser UI (alongside watch mode)
npm run test:ui
# or:
npx vitest --ui
Watch 모드 콘솔 — 네가 살게 될 프롬프트·text
Tests 3 passed (3)
✓ src/lib/format.test.ts (2)
✓ src/lib/parse.test.ts (1)
Test Files 2 passed (2)
Tests 3 passed (3)
Start at 14:23:01
Duration 127ms (transform 19ms, setup 0ms, collect 14ms, tests 8ms)
PASS Waiting for file changes...
press h to show help, press q to quit
필터링 — 인터랙티브 (p/t 키) 나 CLI 인자로·bash
# CLI arg filtering — useful in CI or when you know what you want
# Only files matching pattern
npx vitest format
# Only test names matching pattern (note the -t flag)
npx vitest -t 'rounds to two decimals'
# Run a single file by path
npx vitest src/lib/format.test.ts
# Run a specific test by name + file
npx vitest src/lib/format.test.ts -t 'rounds to two decimals'
`.only` 와 `.skip` — 날카로운 도구, 쓴 후엔 접지·typescript
// Source-level focus — for one-test debugging, not commits
import { describe, it } from 'vitest';
describe('parser', () => {
it.only('handles the weird unicode case', () => {
// While this is here, only this test runs in the file.
// Remove .only before commit — eslint rule should catch it.
});
it('handles the normal case', () => { /* skipped */ });
});
// Or skip a known-broken test temporarily:
it.skip('handles the broken case (tracked in #1234)', () => { /* skipped */ });
Lesson 1 의 프로젝트에서 npm test 로 watch 모드 돌려. 테스트 파일 하나 편집해서 테스트 하나 실패시켜 (toBe(5) 를 toBe(6) 으로). watch 모드가 밀리초 안에 re-run 하고 실패 보여주는 거 봐. f 눌러서 실패한 테스트로 필터. 단언 고쳐. 초록 돌아오는 거 봐. 이제 p 눌러 파일명 패턴 치고 suite 가 좁아지는 거 봐. 루프 느낌 잡아 — 이게 의식이 아닐 때의 테스트 모양이야.
Hint
save 해도 watch 모드가 자동 re-run 안 하면, 에디터가 atomic save (temp 파일로 거치는 방식) 로 watcher 를 혼란시키고 있을 수 있어. 에디터에서 atomic save 설정 찾거나 Vitest 에 --watch.usePolling true 넘겨.
Progress
Progress is local-only — sign in to sync across devices.