Unit test
Security-audited skills for Claude, Codex & Claude Code. One-click install, quality verified.
npx -y skills add aiskillstore/marketplace --skill unit-testAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
What its author says it does
Copied from the file, not written here
기능 단위 테스트 오케스트레이터. Git Diff/사용자 지정 범위에서 테스트 대상을 결정하고, 사용자 시나리오 스토리보드 → 테스트케이스 생성 → Playwright MCP 실행 → 결과 보고. '/unit-test', '단위테스트', '테스트해줘', '기능 테스트' 등 언급 시 호출. 시나리오 단위 회귀 검증(PASS/FAIL/WARN)에 사용하며, 버그 원인 특정·로그 삽입 디버깅이 필요하면 debugger 계열 스킬을 쓴다.
SKILL.md
17.4 KB, as published. Nobody here has run it
UNIT-TEST 기능 단위 테스트
$ARGUMENTS 에 대해 아래 파이프라인을 실행한다.
SCOPE → STORYBOARD → GENERATE → EXECUTE (+ 4.5 VISUAL-UX) → REPORT
분기 — 검증 vs 디버깅
| 상황 | 사용 방식 | 이유 |
|---|---|---|
| 기능이 의도대로 동작하는지 검증 (PASS/FAIL/WARN) | /unit-test | 시나리오 단위 회귀 검증 |
| 버그 현상 발생 — 원인 특정 필요 | 디버깅 워크플로우(예: debugger 스킬) | 가설 도출 → 로그 삽입 → 재현 → 수정/정리 |
| 신규 구현 직후 동작 확인 | /unit-test --happy-only | 빠른 정상 흐름 검증 |
| FAIL 발견 후 원인 추적·수정 | 디버깅 워크플로우로 전환 | unit-test는 검증만, 로그 삽입·정리 미수행 |
--fix플래그가 있어도 unit-test는 단순 재실행(최대 2회)만 수행. 원인 분석·로그 삽입·grep 검증이 필요하면 디버깅 워크플로우로 전환한다.
정적 단위 테스트 게이트와의 관계 (네이밍 주의): 이 스킬은 이름은 "unit-test"지만 실제로는 Playwright 기반 E2E/시나리오 동적 검증이다. vitest/jest 같은 정적 단위 테스트와는 레이어가 다르다 — 둘은 충돌이 아니라 상보다. 정적 단위 테스트(
npm test)는 CI/빌드 게이트에서, 시나리오 동적 검증은 이 스킬에서 담당한다.
옵션 플래그
| 플래그 | 설명 |
|---|---|
--happy-only | Happy Path 시나리오만 생성 (빠른 검증) |
--auto | 승인 없이 전체 파이프라인 연속 실행 |
--fix | FAIL 발견 시 자동 수정 + 재검증 |
--no-ux-review | Phase 4.5 Section B(LLM 폴리시 제안)만 스킵. Section A(design-lint 게이트)는 저비용이라 이 플래그와 무관하게 항상 실행(설치돼 있을 때) |
--strict-visual | Phase 4.5 Section A에 design-lint --strict를 전달(형제 겹침 D-LAYOUT-11 활성, low-confidence 기본 off). design-lint 미설치 시 무의미 |
--gate-visual | Phase 4.5 Section A에 design-lint --gate-runtime을 전달(문서 레벨 가로 오버플로우만 error로 격상 — 해당 시나리오를 FAIL 취급). design-lint 미설치 시 무의미 |
Phase 1: SCOPE (테스트 범위 결정)
테스트 대상을 아래 우선순위로 결정한다.
| 우선순위 | 소스 | 조건 | 수집 방법 |
|---|---|---|---|
| 1 | 사용자 지정 | $ARGUMENTS에 명시적 범위 존재 | 인자 파싱 |
| 2 | Git Diff | 인자 미지정 시 | git diff HEAD~1 --name-only + git diff --cached --name-only → 변경 파일에서 기능 영역 추론 |
| 3 | 최근 작업 맥락 | Diff도 없을 시 (non-git 또는 clean 상태) | 프로젝트의 최근 완료 작업/이슈 기록(있으면)에서 대상 추론, 없으면 사용자에게 대상 확인 |
1-1. 변경 파일 분석
수집된 파일 목록에서:
- 테스트와 무관한 파일 제외 (설정 파일, README, 스타일만 변경 등)
- 남은 파일들의 기능 영역 분류 (컴포넌트, 훅, 유틸, 페이지 등)
- 각 파일을 읽어 사용자에게 노출되는 동작 파악
1-2. 진입점 결정
프로젝트 설정(CLAUDE.md·README·package.json 스크립트 등)에서 개발 서버 포트를 확인하고, 대상 기능의 접근 경로를 결정한다.
1-3. 산출물
[테스트 범위]
대상 기능: {기능명}
소스: 사용자 지정 / Git Diff / 최근 작업 맥락
관련 파일: file1.tsx, file2.ts, ...
진입점 URL: http://localhost:{port}/{path}
선행 조건: {로그인 필요, 특정 데이터 존재 등}
Phase 2: STORYBOARD (사용자 시나리오 설계)
대상 기능의 코드를 읽고 실제 사용자가 수행할 동작 흐름을 예측한다.
2-1. 시나리오 분류
| 유형 | 설명 | 예시 |
|---|---|---|
| Happy Path | 정상 흐름 (필수, 항상 포함) | 폼 입력 → 제출 → 성공 메시지 |
| Edge Case | 경계값·빈값·긴 문자열 | 빈 입력 제출, 특수문자 포함 |
| Error Path | 의도적 오류 유발 | 잘못된 형식 입력, 필수값 누락 |
| Interaction | 복합 인터랙션 | 드래그앤드롭, 키보드 단축키, 연속 클릭 |
--happy-only플래그 시 Happy Path만 생성한다.
2-2. 시나리오 작성
각 시나리오를 아래 형식으로 작성한다:
[S-{N}] {시나리오명}
유형: Happy Path / Edge Case / Error Path / Interaction
전제 조건: {초기 상태 — 페이지, 데이터, 로그인 등}
사용자 동작:
1. {동작} → 기대 반응: {UI 변화}
2. {동작} → 기대 반응: {UI 변화}
...
최종 기대 결과: {상태 / UI / 데이터}
2-3. 사용자 승인
시나리오 목록을 사용자에게 보여주고 피드백을 받는다.
| 응답 | 동작 |
|---|---|
승인 ("ok", "진행해") | Phase 3으로 진행 |
| 수정 지시 | 시나리오 추가/제거/수정 후 재승인 |
| 취소 | 파이프라인 중단 |
--auto플래그 시 승인 없이 즉시 Phase 3으로 진행한다.
Phase 3: GENERATE (테스트케이스 생성)
승인된 시나리오를 Playwright MCP 명령 시퀀스로 변환한다.
3-1. 시나리오별 생성 항목
| 항목 | 내용 |
|---|---|
| 입력 데이터 | 각 인터랙션에 사용할 구체적 값 (텍스트, 클릭 대상, 키 조합) |
| 기대 출력 | 스냅샷에서 확인할 요소 (텍스트 내용, ARIA 속성, 요소 존재/부재) |
| 검증 기준 | PASS/FAIL 판정 조건 (정확히 어떤 상태를 확인하는지) |
| MCP 명령 시퀀스 | Playwright MCP 도구 호출 순서 |
3-2. 명령 시퀀스 구성 규칙
시나리오 시작:
→ browser_navigate(url) # 초기 상태로 이동
→ browser_snapshot() # 초기 상태 확인
동작 수행:
→ browser_click(element) # 클릭
→ browser_type(element, text) # 텍스트 입력
→ browser_press_key(key) # 키보드 입력
→ browser_select_option(...) # 셀렉트 변경
검증:
→ browser_snapshot() # 결과 상태 캡처
→ browser_console_messages() # 콘솔 에러 수집
→ 기대 출력과 비교 # PASS / FAIL 판정
3-3. 검증 판정 기준
| 조건 | 판정 |
|---|---|
| 기대 요소 존재 + 콘솔 에러 없음 | PASS |
| 기대 요소 존재 + 콘솔 경고만 있음 | WARN |
| 기대 요소 부재 또는 콘솔 에러 존재 | FAIL |
이 표는 기능(콘솔·DOM) 판정 전용이며 상태값(PASS/FAIL/WARN)은 이 조건에서만 바뀐다. "동작은 정상인데 시각적으로 깨진 것"(오버플로우·텍스트 잘림·버튼 텍스트 초과)은 이 표를 건드리지 않는다 — Phase 4.5에서 별도 애노테이션(
🎨 UX결함)으로만 부가한다. 두 레이어를 섞지 않는 이유: 기능 회귀와 시각 폴리시는 원인·수정 담당·긴급도가 다르고, 섞으면 "왜 PASS였던 시나리오가 갑자기 FAIL됐지"를 콘솔 에러 때문인지 레이아웃 때문인지 구분 못 하게 된다.
3-4. 안전장치
- 스냅샷 전 핵심 DOM 요소 존재 확인 — SPA 라우팅/렌더링 완료 대기
- 비결정적 데이터(타임스탬프, UUID 등)는 존재 여부만 검증, 정확한 값 비교 제외
- 암호화 필드는 UI 레벨 표시값으로만 검증
Phase 4: EXECUTE (테스트 실행)
4-0. 사전 체크
① 테스트용 백엔드 서비스 확인 (해당 시)
테스트에 DB·Redis 등 백엔드 서비스가 필요하면, 프로젝트의 기존 방식(예: docker-compose up -d, 로컬 서비스, .env의 테스트용 접속 정보)으로 기동한다. 이 스킬은 별도 인프라를 제공하지 않는다 — 운영 데이터를 건드리지 않도록 테스트 전용 인스턴스/DB를 사용하는 것을 권장한다.
- 백엔드가 필요 없는 순수 프론트엔드/정적 대상이면 이 단계는 스킵.
② 개발 서버 실행 여부 확인
browser_navigate → 진입점 URL
미실행 시 → 사용자에게 안내 후 파이프라인 중단
⚠ 개발 서버가 실행되지 않았습니다.
→ 개발 서버를 실행한 후 다시 /unit-test 를 실행해 주세요.
4-1. 실행 루프
각 시나리오를 순서대로 실행한다:
for each scenario S-{N}:
1. browser_navigate → 초기 URL (매 시나리오마다 초기화)
2. browser_snapshot → 초기 상태 확인
3. 동작 시퀀스 실행 (click, type, press_key 등)
- 각 동작 후 필요 시 중간 스냅샷으로 상태 확인
- 시나리오 유형이 Interaction(드래그앤드롭·키보드단축키·연속클릭 등 과도기 상태가 있는 유형)이면
중간 스냅샷 시점에도 Phase 4.5 Section A를 조건부 실행한다 — 드롭다운 열림·호버 툴팁처럼
"동작 중"에만 나타나고 최종 정착 상태에선 사라지는 시각 결함은 최종 스냅샷만 봐서는 놓친다.
4. browser_snapshot → 최종 상태 캡처
5. browser_console_messages → 에러 수집
6. 기대 출력 vs 실제 결과 비교 → PASS / FAIL / WARN (기능 판정, 3-3 기준)
7. Phase 4.5 VISUAL-UX 실행 → 이 시나리오의 시각 결함을 별도 애노테이션으로 수집 (상태값은 안 바꿈)
4-2. FAIL 처리
- 실패 시나리오의 스냅샷 상태 + 콘솔 에러 + 기대값/실제값 차이를 기록
- 다음 시나리오는 계속 진행 (전체 중단하지 않음)
--fix플래그 시: FAIL 발견 즉시 코드 수정 → 해당 시나리오만 재실행 (최대 2회)- Phase 4.5의 시각 결함(UX결함)은
--fix트리거 대상이 아니다.--fix는 기능 FAIL(3-3 기준: 기대요소 부재/콘솔에러) 전용이며, 시각 결함은 게이트가 아니라 보고 항목이므로 자동 수정 흐름에 섞이지 않는다.
4-3. Chrome DevTools MCP 에스컬레이션 (FAIL 원인 불명 시, 선택)
Playwright browser_console_messages로 원인 특정 불가 시, chrome-devtools MCP가 설치돼 있으면 순차 사용한다(이 플러그인은 playwright만 동봉하므로 chrome-devtools는 별도 설치 시에만 사용 가능).
Playwright 도구 완료 후에만 호출 — 동시 사용 금지.
| 증상 | 사용할 DevTools 도구 |
|---|---|
| API 요청 실패 의심 | getNetworkRequests |
| 응답 데이터 확인 필요 | getNetworkRequests + 응답 바디 |
| 렌더링 성능 문제 | getCoreWebVitals |
| 원인 불명 — 현재 DOM 구조 확인 | getDocument |
DevTools 수집 완료 후 → Phase 5 REPORT에 원인 포함해서 보고. (chrome-devtools 미설치 시 이 단계는 스킵하고, 수집된 스냅샷·콘솔 정보만으로 보고한다.)
Phase 4.5: VISUAL-UX (동작은 정상, 시각만 깨진 것 검사)
왜 별도 Phase인가: Phase 3-3의 기능 판정(PASS/FAIL/WARN)은 "의도대로 동작하는가"만 본다. "동작은 되는데 인터랙션 후 섹션이 틀어지거나, 버튼 텍스트가 잘리거나, 카드가 겹치는" 건 기능 버그가 아니라 UX 결함이라 별도 레이어로 다룬다. 각 시나리오의 (최종, 그리고 Interaction 유형은 필요 시 중간) 스냅샷 직후 실행하며, Section A/B는 신뢰수준이 다르므로 REPORT에서 항상 구분 표기한다.
각 시나리오의 관측 대상 상태(4-1 step 3~4)에서:
사전 공통 — DOM 덤프 (Section A/B 공유 입력)
먼저 현재 상태의 DOM outerHTML을 인라인 <style> 형태로 1회 덤프한다. 이 덤프는 Section A(설치 시)와 Section B(실행 시) 양쪽이 재사용하므로, design-lint 설치 여부·--no-ux-review 여부와 무관하게 항상 생성한다(재수집 금지).
A. 결정론 게이트 — design-lint 런타임 detector (design-lint 플러그인이 함께 설치돼 있으면)
같은 마켓의 design-lint 플러그인이 설치돼 있으면 아래를 실행한다(미설치 시 Section A 전체 스킵 — 이 스킬은 자립적으로 동작하며 design-lint는 선택적 강화다):
browser_evaluate('document.fonts.ready')로 폰트 로딩 완료를 먼저 대기한다(웹폰트 스왑 전 관측은 폴백폰트 metric으로 인한 일시적 오버플로우 오탐을 유발).- design-lint의
--observe-snippet으로 관측 스니펫을 얻어browser_evaluate에 주입 → 반환 배열을obs.json으로 저장 (뷰포트 1280×800 고정 필수 — Section A 전체의 결정론 전제). - design-lint를
<dump.html>(위 공통 덤프)--observed obs.json [--strict-visual 시 --strict] [--gate-visual 시 --gate-runtime]로 실행한다. D-LAYOUT-08(가로 오버플로우) ·D-LAYOUT-09(텍스트 잘림) ·D-LAYOUT-10(버튼 텍스트 초과) · (--strict-visual시)D-LAYOUT-11(형제 겹침, low-confidence) warn을 수집.- 판정에 영향 없음 — 기능 PASS는 그대로 유지, 발견된 항목은 시나리오에
🎨 UX결함애노테이션으로만 부가한다. 단--gate-visual로 문서 레벨(html/body) 가로 오버플로우가 error로 격상된 경우는 해당 시나리오를 예외적으로 FAIL 취급한다(명시적 opt-in 시에만).
design-lint를 호출할 때 플러그인 설치 경로를 하드코딩하지 않는다 — 슬래시 커맨드/스킬로 노출된 형태를 사용하거나, 프로젝트에 스크립트가 존재하면 그 경로로 호출한다. 경로를 모르면 Section A를 건너뛰고 Section B(스크린샷 기반)만 수행한다.
B. 폴리시 제안 — LLM 리뷰 (--no-ux-review 시 스킵)
- 입력: 현재 상태 스크린샷 + 위 공통 DOM 덤프(재수집 금지).
references/interface-polish-rules.md의 9룰(concentric radius·optical alignment·shadow depth·text-wrap·font-smoothing·image outline·motion enter/exit 비대칭·press state·tabular-nums)을 참고해 "동작은 OK지만 미감이 아쉬운" 항목을 제안.- 게이트 아님, 참고용(비재현) — PASS/FAIL/WARN 상태값도,
--fix트리거도 건드리지 않는다. - 비용 통제: Section A(설치 시)가 이미 결함을 찾은 시나리오만 우선 실행하거나(권장),
--no-ux-review로 전체 스킵 가능.--happy-only와는 무관하게 저비용 항목은 유지하고 고비용 LLM 리뷰만 통제한다.
Phase 5: REPORT (결과 보고)
5-1. 결과 요약
╔══════════════════════════════════════╗
║ Unit Test 결과 ║
╠══════════════════════════════════════╣
║ 대상: {기능명} ║
║ 시나리오: {총}개 실행 ║
║ ✅ PASS: {n} ❌ FAIL: {n} ⚠ WARN: {n} ║
║ 🎨 UX결함: {n} (시각, 기능 상태 무관) ║
╚══════════════════════════════════════╝
🎨 UX결함은 Phase 4.5에서 수집된 시각 결함 개수다. PASS/FAIL/WARN 집계와 별도이며 콘솔 경고(기존 WARN)와 절대 합산하지 않는다 — 원인(콘솔 vs 시각)을 구분 못 하게 되는 걸 막기 위함.
5-2. 시나리오별 상세
[S-1] ✅ {시나리오명} — PASS
[S-2] ❌ {시나리오명} — FAIL
├ 실패 지점: 동작 {N} 이후
├ 기대: {기대 상태}
├ 실제: {실제 상태}
└ 콘솔: {에러 메시지 또는 "없음"}
[S-3] ⚠ {시나리오명} — WARN
└ 경고: {콘솔 경고 내용}
[S-4] ✅ {시나리오명} — PASS 🎨 UX결함 2건
├ [A/게이트] D-LAYOUT-09 텍스트 잘림(말줄임 없음): .card-title
├ [A/게이트] D-LAYOUT-10 버튼 텍스트 초과: button.submit
└ [B/제안·비재현] .cart-count에 tabular-nums 권장(자릿수 변할 때 흔들림)
5-3. 후속 액션
| 결과 | 동작 |
|---|---|
| 전체 PASS | 완료 메시지 출력 |
FAIL 존재 + --fix | 자동 수정 시도 (Phase 4-2에서 이미 처리) |
FAIL 존재 + --fix 없음 | 사용자에게 수정 여부 확인 |
사용자 응답:
| 입력 | 동작 |
|---|---|
"수정해줘" | 실패 원인 분석 → 코드 수정 → 실패 시나리오만 재실행 |
"괜찮아" / "종료" | 보고서 출력 후 종료 |
Known Pitfalls
본 skill 실행 중 반복 발생한 실패 패턴. 신규 패턴 발견 시 entry를 추가한다.
(현재 누적 entry 없음.)
작성 형식
- [패턴명] — YYYY-MM-DD
- 상황: 어떤 단계(시나리오 생성/실행/검증)·조건에서 발생
- 원인: 무엇 때문에 실패 (시나리오 누락 / mock 오류 / 환경 문제 등)
- 회피: 다음 실행 시 적용할 가이드