TDD문화 도입 | (1) Vitest 전환과 커버리지 기반 품질 관리
TDD문화 도입 | (1) Vitest 전환과 커버리지 기반 품질 관리
📌 이 글은 TDD 시리즈 중 1편입니다.
2편: 주간 커버리지 대시보드로 시각화하기
3편: 커버리지 측정 및 자동화 시스템 구축 (GitLab + Vitest)
4편: Tech 발표, Vitest로 안정적인 프론트엔드 개발하기
1. 문제 상황 또는 동기 (Motivation)
- 기존에는 테스트 코드의 필요성을 크게 느끼지 못했으나, 실제 서비스 운영 중 잦은 회귀 버그와 코드 변경에 대한 불안감이 있었습니다.
- 모닥불 테스트코드 영상과 프런트엔드 개발을 위한 테스트 입문 서적을 접하며 테스트의 중요성을 인식하게 되었습니다.
- 기존 Jest 환경은 다음과 같은 한계가 있었습니다:
- 설정이 복잡하고 느린 테스트 속도
- Vue2 SFC 지원의 불편함
- CI/CD 파이프라인에서의 실행 비용 증가
👉 이런 문제를 해결하고자 Vitest 전환 + TDD 문화 도입을 결정했습니다.
2. 목표 및 요구사항 (Goal & Requirements)
- 신규 기능/버그 수정 시 TDD 사이클을 적용하여 품질을 높임
- AI 에이전트 기반 SB(Test Spec) → AAA 패턴 테스트케이스 자동화
- 커버리지 변화 추이를 관리할 수 있는 대시보드 구축
- GitLab CI에 자동 테스트 검증 프로세스 추가
- 최종적으로는 60% 이상 커버리지 달성 및 장기적 TDD 문화 정착
3. 구현 과정 (Implementation)
3.1 Vitest 환경 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
globals: true,
include: ['__vitest__/**/*.test.{js,ts,tsx}'],
reporters: ['default', 'junit'],
coverage: {
provider: 'v8',
reporter: ['html', 'json-summary', 'text', 'cobertura'],
}
}
})
3.2 테스트코드 표준화
📂 디렉토리 구조
- 모든 테스트 파일은
__vitest__디렉토리에 위치 - 파일 네이밍:
*.test.js,*.spec.js - 소스 코드와 테스트 코드가 1:1 매핑되도록 동일한 폴더 구조 유지
✍ 작성 규칙
1
2
3
4
5
6
7
8
9
10
11
describe("컴포넌트명.vue", () => {
describe("모듈 노출케이스", () => {
// 정상 케이스
});
describe("모듈 비노출케이스", () => {
// 예외 상황
});
describe("기능 검증", () => {
// 세부 기능
});
});
1
2
3
4
5
6
7
8
9
10
11
12
describe("TravelSearch.vue", () => {
describe("기능 검증", () => {
it("정상 데이터 입력 시 결과가 노출된다", async () => {
// Arrange
const wrapper = mount(TravelSearch, { props: { query: "제주" } })
// Act
await wrapper.find("button.search").trigger("click")
// Assert
expect(wrapper.find(".result").exists()).toBe(true)
})
});
})
Vitest 테스트 코드 작성 규칙(Cursor, Cline rules)
절대 원칙
테스트 파일을 제외한 다른 파일은 수정하면 안된다
0. TDD(Test Driven Development) 방법론
기본 원칙
- 모든 기능/버그 수정 시에도 TDD 사이클(Red-Green-Refactor)을 따른다.
작업 순서
- SB 작성 완료 후:
- 요건을 정리하여 테스트 코드를 먼저 작성한다.
- 이 시점의 테스트는 반드시 실패(Red)해야 한다.
- 데이터 스키마 수신 후:
- 정상 케이스, 비정상 케이스에 대한 테스트 데이터를 세팅한다.
- 각 케이스별 예상 결과를 명확히 정의한다.
- 실제 구현:
- 작업 진행 중 테스트 성공(Green)을 지속적으로 확인한다.
- 모든 케이스에 대해 테스트가 통과하는지 확인한다.
- 리팩토링:
- 코드 품질 개선
- 테스트 유지 보수
1. 파일 위치 및 네이밍
- 테스트 파일은 소스와 동일한 폴더에
*.test.js,*.test.ts,*.spec.js,*.spec.ts또는__vitest__폴더에 작성한다. - 예시:
Button.test.js,utils.spec.ts
2. 테스트 구조
describe로 테스트 단위(컴포넌트/함수)를 그룹화한다.- 동일 컴포넌트/함수 내에서도 “주요 기능 단위”로 describe를 분리하여 작성한다. (예: 노출 조건, 데이터 변환, 이벤트 등)
it또는test로 개별 동작을 명확히 작성한다.
2-1. describe 대분류 작성 권장
- 컴포넌트 테스트 시, 주요 시나리오별로 describe 블록을 아래와 같이 크게 구분하여 작성한다.
- 모듈 노출케이스: 정상적으로 모듈이 노출되는 조건/상황을 검증
- 모듈 비노출케이스: 필수 데이터 미존재 등으로 모듈이 노출되지 않는 조건을 검증
- 기능 검증: 스타일, 동작, 이벤트 등 세부 기능을 검증
- 예시:
1 2 3 4 5
describe("모듈명.vue", () => { describe("모듈 노출케이스", () => { ... }); describe("모듈 비노출케이스", () => { ... }); describe("기능 검증", () => { ... }); });
- 실제 예시는 vitest/travel_search.test.js 참고
3. AAA 패턴 적용
- Arrange(준비), Act(실행), Assert(검증) 순서로 작성한다.
4. 단일 책임 원칙
- 하나의 테스트는 하나의 동작만 검증한다.
5. 명확한 테스트명
- 테스트 목적이 드러나도록 한글 또는 영어로 명확하게 작성한다.
6. Mock/Stub 적극 활용
- 외부 의존성(네트워크, 타 모듈 등)은 mocking/stubbing 한다.
7. 비동기 테스트는 async/await 사용
- 비동기 함수 테스트 시
async/await을 사용한다.
8. 스냅샷 테스트는 신중하게 사용
- UI 변경이 잦은 경우 스냅샷 테스트는 최소화한다.
9. 테스트 커버리지 목표
- 전체 커버리지 80% 이상을 목표로 한다.
10. 테스트 독립성 보장
- 테스트 간 상태를 공유하지 않는다.
- 각 테스트는 독립적으로 실행되어야 한다.
3.3 커버리지 기반 품질 관리
- v8 provider 기반 커버리지 측정
- HTML + JSON 보고서 생성
- GitLab CI/CD와 연동하여 MR 시점 자동 검증
- 주간 커버리지 집계 → Bigbro 대시보드에 업로드
실제 시뮬레이션 예시
- 전체 코드: 206,410 LOC
- 컴포넌트 코드: 128,163 LOC (543개 파일)
- 컴포넌트 100% 테스트 시 전체 커버리지: 62.1%
- 파일 1개(236 LOC) 테스트 → 전체 커버리지 약 0.11%p 상승
3.4 시행착오/트러블슈팅
- E2E 기반으로 출발했다가 실패
- Playwright-MCP 활용 → 동적 컴포넌트 설정 탓에 일관성 부족
- 단위 테스트(TDD)부터 시작 → 점진적으로 UI/E2E 확장 전략으로 전환
- Composition API 전환
- Options API 기반 테스트가 깨짐
- Composition API 전용 global setup을 구성해 해결
- AI 역-작성 규칙 문제
- 기존 코드에 맞춰 테스트를 생성 → TDD 흐름과 맞지 않음
- SB 기반 요건 → 테스트 순서로 프로세스를 수정
- Node 버전 이슈
- Node 16 환경에서는 Vitest 2.x 실행 불가
- Node 18+에서 정상 동작, 이후 Node 22 업그레이드 완료
4. 결과 및 느낀 점 (Result & Retrospective)
- TDD 도입 후 신규 기능/버그 수정 시 안정감이 크게 향상됨
- SB 기반 테스트케이스가 요건 문서 역할을 하여 협업 및 코드 리뷰 효율 증가
- 테스트 목적과 범위를 고민하게 되면서 코드 품질 인식 제고
- 커버리지 관리 대시보드로 테스트 사각지대 파악 용이
- Vitest 전환을 통해 테스트 실행 속도 및 DX 개선
- 앞으로는 E2E/UI 테스트 자동화까지 확장 계획
5. 기술 스택 (Tech Stack)
Vue JavaScript Vite Vitest @vue/test-utils Vitest/ui Vitest/coverage-v8
Next.js TypeScript React Webpack CoreUI/React
GitLab GitLab CI Docker
6. 참고 자료 (References)
🥇중간 성과 (Interim Achievements)
- 9월 9일 커버리지 20% 돌파
- 9월 26일 팀원들과의 협업으로 현재 커버리지 25% 이상 달성
추신.
본 게시물의 기여도 75%는 초기 Vitest 환경 설정, 테스트 표준화, TDD 문화 도입 등 전체적인 테스트 시스템을 구축하고 초기 테스트 코드(커버리지 16.9%)를 작성한 기여를 의미합니다.”
함께 더 나은 테스트코드를 위해 힘써주시는 준희님(Core Contributor)과 한나님(Contributor)께 감사를 전합니다.😊
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.