huh test는 ErrorConfig JSON을 기반으로 Playwright 브라우저를 실행하여 각 에러 항목의 UI를 스크린샷으로 캡처하고, 확장 검증(Extended Validation)을 수행한 뒤 HTML 리포트를 자동 생성합니다.
사전 요구사항
Playwright가 설치되어 있어야 합니다.
TIP
huh test는 내부적으로 headless Chromium을 사용합니다. CI 환경에서는 반드시 Playwright 브라우저가 설치된 이미지를 사용하세요.
기본 사용법
# 기본 실행 (standalone 모드, desktop, src/huh.json)
npx huh test
# 모바일 디바이스로 캡처
npx huh test --device mobile
# 특정 trackId만 테스트
npx huh test --filter ERR_AUTH,ERR_NOT_FOUND
# 리포트를 브라우저에서 열기
npx huh test --open
# 이전 리포트와 비교 (diff)
npx huh test --diff
# CI 모드 (실패 시 exit code 1)
npx huh test --ciCLI 옵션
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
--mode <mode> | standalone | app | standalone | 미리보기 모드 |
--url <url> | string | — | 앱 URL (app 모드에서 필수) |
--config <path> | string | src/huh.json | ErrorConfig JSON 파일 경로 |
--output <dir> | string | .huh-report | 리포트 출력 디렉토리 |
--filter <ids> | string | — | 테스트할 trackId (쉼표 구분) |
--type <types> | string | — | 필터할 에러 타입 (쉼표 구분) |
--device <preset> | desktop | mobile | tablet | desktop | 디바이스 프리셋 |
--open | boolean | false | 생성 후 브라우저에서 리포트 열기 |
--ci | boolean | false | CI 모드: 실패 시 exit code 1 |
--diff | boolean | false | 이전 리포트와 비교 |
동작 흐름
ErrorConfig 로드
--config 경로에서 JSON 파일을 읽어 ErrorConfig를 파싱합니다. .huh.config.json에 simulate 설정이 있으면 함께 로드합니다.
trackId 필터링
--filter와 --type 옵션에 따라 테스트 대상 trackId를 필터링합니다.
프리뷰 서버 시작
내부 HTTP 서버를 시작하여 각 에러 항목을 독립적인 HTML 페이지로 렌더링합니다. TOAST, MODAL, PAGE 타입에 맞는 내장 렌더러가 자동으로 적용됩니다.
Playwright 스크린샷 캡처
Headless Chromium이 각 에러 항목 페이지를 방문하여 스크린샷을 캡처합니다. 타입별 대기 시간이 적용됩니다: - TOAST: 350ms - MODAL: 250ms - PAGE: 400ms
확장 검증 (Extended Validation)
@sanghyuk-2i/huh-core의 기본 검증 + 추가 확장 검증을 실행합니다. 아래 확장 검증 섹션 참고.
HTML 리포트 생성
스크린샷(base64 인코딩)과 검증 결과를 포함한 report.html 및 report-data.json을 생성합니다.
디바이스 프리셋
| 프리셋 | 해상도 | Scale Factor | 모바일 |
|---|---|---|---|
desktop | 1280 x 720 | 1x | No |
mobile | 375 x 812 | 2x | Yes |
tablet | 768 x 1024 | 2x | Yes |
# 모바일 뷰포트로 테스트
npx huh test --device mobile
# 태블릿 뷰포트로 테스트
npx huh test --device tablet시뮬레이션 설정
.huh.config.json에 simulate 필드를 추가하여 테스트 시 템플릿 변수와 타이밍을 제어할 수 있습니다.
{
"source": { "type": "csv", "filePath": "./errors.csv" },
"output": "./src/huh.json",
"simulate": {
"defaultVariables": {
"userName": "홍길동",
"count": "5"
},
"variables": {
"ERR_AUTH": {
"userName": "관리자"
}
},
"waitTimeout": 10000,
"screenshotDelay": 500
}
}| 필드 | 타입 | 설명 |
|---|---|---|
defaultVariables | Record<string, string> | 모든 trackId에 적용되는 기본 변수 |
variables | Record<string, Record<string, string>> | trackId별 개별 변수 (defaultVariables를 오버라이드) |
waitTimeout | number | 렌더 완료 대기 제한 시간 (ms) |
screenshotDelay | number | 렌더 완료 후 스크린샷 캡처 전 추가 대기 (ms) |
TIP
variables에 trackId별 값이 있으면 defaultVariables의 같은 키를 오버라이드합니다. 예를 들어 위 설정에서 ERR_AUTH의 userName은 "관리자"가 되고, 다른 trackId에서는 "홍길동"이 됩니다.
확장 검증
huh test는 @sanghyuk-2i/huh-core의 기본 검증에 더해 다음의 확장 검증을 수행합니다:
| 검사 항목 | 심각도 | 설명 |
|---|---|---|
render-failure | error | Playwright에서 에러 UI 렌더링에 실패한 경우 |
image-url-broken | warning | image 필드의 URL이 유효하지 않은 경우 |
message-too-long | warning | 메시지 길이가 타입별 권장 길이를 초과한 경우 |
slow-render | warning | 렌더링 시간이 3000ms를 초과한 경우 |
missing-template-variable | warning | 치환되지 않은 \{\{variable\}\} 패턴이 남아있는 경우 |
메시지 길이 제한 (권장):
| 타입 | 최대 글자 수 |
|---|---|
| TOAST | 120자 |
| MODAL | 500자 |
| PAGE | 300자 |
출력 파일
--output 디렉토리(기본값: .huh-report)에 다음 파일이 생성됩니다:
| 파일 | 설명 |
|---|---|
report.html | 스크린샷과 검증 결과가 포함된 시각적 리포트 (base64 이미지 임베딩) |
report-data.json | 프로그래밍 방식으로 활용 가능한 구조화된 리포트 데이터 (스크린샷 미포함) |
report-data.json 구조:
{
"generatedAt": "2025-01-15T09:30:00.000Z",
"device": { "name": "Desktop", "width": 1280, "height": 720 },
"mode": "standalone",
"totalEntries": 5,
"passCount": 4,
"failCount": 1,
"warningCount": 2,
"entries": [
{
"trackId": "ERR_AUTH",
"type": "MODAL",
"renderTimeMs": 180,
"success": true,
"validationIssues": [],
"coreValidationErrors": [],
"coreValidationWarnings": []
}
]
}Diff 모드
--diff 옵션을 사용하면 이전에 생성된 report-data.json과 현재 결과를 비교합니다.
감지 항목:
| 상태 | 설명 |
|---|---|
added | 새로 추가된 trackId |
removed | 삭제된 trackId |
changed | 타입, 성공/실패 상태, 이슈 수가 변경된 항목 |
unchanged | 변경 없는 항목 |
출력 예시:
Diff: 1 added, 0 removed, 1 changed, 3 unchanged
+ ERR_TIMEOUT: new entry (type: TOAST)
~ ERR_AUTH: status changed (fail → pass)CI/CD 통합
on:
pull_request:
paths:
- 'src/huh.json'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install
- run: npx playwright install chromium
- name: Run huh test
run: npx huh test --ci --diff
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: huh-report
path: .huh-report/WARNING
--ci 모드에서는 1개 이상의 에러(render-failure 등)가 있으면 exit code 1로 종료됩니다. 경고(warning)만 있는 경우에는 통과합니다.
필터링
trackId 필터
특정 trackId만 테스트합니다:
타입 필터
특정 에러 타입만 테스트합니다:
# TOAST 타입만 테스트
npx huh test --type TOAST
# MODAL과 PAGE 타입 테스트
npx huh test --type MODAL,PAGE필터 조합
--filter와 --type을 함께 사용하면 두 조건을 모두 만족하는 항목만 테스트합니다:
# TOAST 타입 중 특정 trackId만
npx huh test --filter ERR_NETWORK,ERR_SAVE --type TOAST