📝 docs: 여러 문서 및 파일 삭제
This commit is contained in:
160
.claude/skills/dev-unit-test/SKILL.md
Normal file
160
.claude/skills/dev-unit-test/SKILL.md
Normal file
@@ -0,0 +1,160 @@
|
||||
---
|
||||
name: dev-unit-test
|
||||
description: |
|
||||
Vue 3 컴포넌트를 받아 Vitest + Vue Test Utils 기반의 단위 테스트를 자동 생성합니다.
|
||||
Props, Emits, 슬롯, 사용자 인터랙션, 비동기 동작을 모두 커버합니다.
|
||||
|
||||
다음 상황에서 반드시 사용하세요:
|
||||
- "이 컴포넌트 단위 테스트 작성해줘", "테스트 코드 만들어줘"
|
||||
- "Vitest 어떻게 써?", "Vue Test Utils 사용 방법"
|
||||
- 컴포넌트 완성 후 커버리지를 확보해야 할 때
|
||||
---
|
||||
|
||||
# 단위 테스트 생성 (dev-unit-test)
|
||||
|
||||
`.vue` 컴포넌트 → Vitest + Vue Test Utils 단위 테스트 자동 생성.
|
||||
|
||||
## 언제 사용하는가
|
||||
|
||||
- 컴포넌트 개발 완료 후 테스트 코드를 작성할 때
|
||||
- TDD 방식으로 테스트를 먼저 작성할 때
|
||||
- 팀 테스트 커버리지 기준(80%↑)을 달성해야 할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- 테스트할 `.vue` 파일 경로
|
||||
- 테스트 케이스 범위 (없으면 자동 도출)
|
||||
|
||||
---
|
||||
|
||||
## 작업 순서
|
||||
|
||||
### Phase 1: 컴포넌트 분석
|
||||
|
||||
1. 대상 `.vue` 파일을 읽어 아래 항목을 파악한다.
|
||||
- Props 목록 (타입, 기본값, 필수 여부)
|
||||
- Emits 목록 (이벤트 이름, 페이로드 타입)
|
||||
- 슬롯 유무
|
||||
- 외부 의존성 (composables, store, $fetch)
|
||||
- 인터랙션 (버튼 클릭, 입력, 폼 제출)
|
||||
- 비동기 동작 (API 호출, 로딩 상태)
|
||||
- 조건부 렌더링 (`v-if`, `v-show`)
|
||||
|
||||
2. 테스트 케이스 목록을 도출한다.
|
||||
|
||||
### Phase 2: 테스트 설정
|
||||
|
||||
```ts
|
||||
// vitest.config.ts (없으면 생성 안내)
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
globals: true,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 3: 테스트 파일 생성
|
||||
|
||||
파일 위치: 컴포넌트와 동일 디렉토리 또는 `__tests__/` 폴더.
|
||||
파일명: `<ComponentName>.spec.ts`
|
||||
|
||||
```ts
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import ComponentName from './ComponentName.vue'
|
||||
|
||||
describe('ComponentName', () => {
|
||||
// Phase 4 케이스 작성
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 4: 테스트 케이스 작성 패턴
|
||||
|
||||
#### Props 검증
|
||||
```ts
|
||||
it('title prop을 렌더링한다', () => {
|
||||
const wrapper = mount(ComponentName, {
|
||||
props: { title: '테스트 제목' }
|
||||
})
|
||||
expect(wrapper.find('h2').text()).toBe('테스트 제목')
|
||||
})
|
||||
|
||||
it('필수 prop 누락 시 기본값을 사용한다', () => {
|
||||
const wrapper = mount(ComponentName)
|
||||
expect(wrapper.find('[data-testid="label"]').text()).toBe('기본값')
|
||||
})
|
||||
```
|
||||
|
||||
#### Emits 검증
|
||||
```ts
|
||||
it('버튼 클릭 시 click 이벤트를 emit한다', async () => {
|
||||
const wrapper = mount(ComponentName, { props: { id: '1' } })
|
||||
await wrapper.find('button').trigger('click')
|
||||
expect(wrapper.emitted('click')?.[0]).toEqual(['1'])
|
||||
})
|
||||
```
|
||||
|
||||
#### 조건부 렌더링
|
||||
```ts
|
||||
it('isLoading이 true이면 스피너를 표시한다', () => {
|
||||
const wrapper = mount(ComponentName, { props: { isLoading: true } })
|
||||
expect(wrapper.find('[aria-busy="true"]').exists()).toBe(true)
|
||||
expect(wrapper.find('[data-testid="content"]').exists()).toBe(false)
|
||||
})
|
||||
```
|
||||
|
||||
#### 비동기 / 스토어 Mock
|
||||
```ts
|
||||
import { createTestingPinia } from '@pinia/testing'
|
||||
|
||||
it('마운트 시 fetchProducts를 호출한다', async () => {
|
||||
const wrapper = mount(ComponentName, {
|
||||
global: {
|
||||
plugins: [createTestingPinia({ createSpy: vi.fn })]
|
||||
}
|
||||
})
|
||||
const store = useProductStore()
|
||||
expect(store.fetchProducts).toHaveBeenCalledOnce()
|
||||
})
|
||||
```
|
||||
|
||||
#### 슬롯
|
||||
```ts
|
||||
it('default 슬롯 콘텐츠를 렌더링한다', () => {
|
||||
const wrapper = mount(ComponentName, {
|
||||
slots: { default: '<span>슬롯 내용</span>' }
|
||||
})
|
||||
expect(wrapper.find('span').text()).toBe('슬롯 내용')
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```
|
||||
## 단위 테스트: <ComponentName>.spec.ts
|
||||
|
||||
### 테스트 케이스 목록
|
||||
1. [렌더링] 기본 렌더링 성공
|
||||
2. [Props] title prop 표시
|
||||
3. [Emits] 버튼 클릭 시 emit
|
||||
4. [조건부] isLoading 상태 처리
|
||||
...
|
||||
|
||||
### 코드
|
||||
\`\`\`ts
|
||||
[전체 spec 파일]
|
||||
\`\`\`
|
||||
|
||||
### 실행 방법
|
||||
\`\`\`bash
|
||||
npx vitest run <파일경로>
|
||||
npx vitest --coverage # 커버리지 확인
|
||||
\`\`\`
|
||||
```
|
||||
Reference in New Issue
Block a user