Vitest

Vite 기반의 빠르고 현대적인 단위 테스트 프레임워크입니다.
Vite의 설정과 플러그인을 그대로 활용할 수 있어 별도의 복잡한 설정 없이 테스트 환경을 구축할 수 있습니다.

주요 특징

  • 빠른 실행 속도
    Vite의 ESM 기반 변환과 HMR(Hot Module Replacement)을 활용하여 테스트를 빠르게 실행하고, 파일 변경 시 관련된 테스트만 다시 실행합니다.
  • Jest 호환 API
  • TypeScript 및 JSX 지원
  • Watch 모드
    파일 변경을 감지하여 자동으로 테스트를 재실행하며, 스마트한 필터링으로 변경된 부분과 관련된 테스트만 실행
  • UI 모드
    브라우저에서 테스트 결과를 시각적으로 확인할 수 있는 UI 제공

기본 설정

// package.json
{
  "scripts": {
    "test": "vitest",
    "test:ui": "vitest --ui",
    "test:run": "vitest run"
  }
}
// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
    test: {
        globals: true,
        environment: 'jsdom', // 'node', 'jsdom', 'happy-dom' 등
        setupFiles: './src/test/setup.ts', // 전역 테스트 환경 설정
    },
});

Setup과 Teardown

테스트 실행 전후에 특정 작업을 자동으로 수행하는 기능으로 테스트 환경을 준비하고 정리하는 용도로 사용합니다.
기본적으로는 파일 단위로 격리되어 동작하고, 전역 혹은 여러 파일에 공통 적용하려면 vitest.config.ts에 setupFiles 에 setup.ts 파일 경로를 지정해주면 됩니다.

  • 전역 + 로컬 파일 모두 있을 경우,
    전역 beforeAll → 로컬 beforeAll → 테스트 실행 → 로컬 afterAll -> 전역 afterAll 순서로 실행

주요 역할

  • 테스트 독립성 보장: 각 테스트가 서로 영향을 주지 않도록 매번 깨끗한 상태에서 시작할 수 있습니다.
  • 중복 코드 제거: 여러 테스트에서 반복되는 준비 작업을 한 곳에서 관리할 수 있습니다.
  • 리소스 관리: 데이터베이스 연결, 파일 핸들 등 리소스를 적절히 생성하고 정리할 수 있습니다.
  • 테스트 신뢰성 향상: 일관된 초기 상태를 보장하여 테스트 결과의 신뢰성을 높입니다.

주요 함수

  • beforeAll: 모든 테스트가 시작되기 전에 딱 1번만 실행
  • afterAll: 모든 테스트가 끝난 후에 딱 1번만 실행
  • beforeEach: 각각의 테스트가 실행되기 전마다 매번 실행
  • afterEach: 각각의 테스트가 끝날 때마다 매번 실행

Fixture

테스트를 실행하기 위해 필요한 고정된 상태나 데이터 환경을 의미합니다.
테스트가 일관되고 예측 가능한 조건에서 실행될 수 있도록 사전에 준비된 데이터나 객체를 제공합니다.

주요 역할

  • 테스트 데이터 준비: 테스트에 필요한 초기 데이터나 객체를 미리 설정
  • 일관성 보장: 모든 테스트가 동일한 초기 상태에서 시작하도록 보장
  • 재사용성: 여러 테스트에서 동일한 설정을 반복 사용
  • 격리성: 각 테스트가 독립적으로 실행되도록 환경 구성

사용 예시

import { beforeEach, describe, it, expect } from 'vitest';

describe('User Service', () => {
    // Fixture: 테스트용 사용자 데이터
    let testUser: User;

    beforeEach(() => {
        // 각 테스트 전에 fixture 초기화
        testUser = {
            id: 1,
            name: 'John Doe',
            email: 'john@example.com',
        };
    });

    it('should update user name', () => {
        // testUser fixture를 사용
        const result = updateUserName(testUser, 'Jane Doe');
        expect(result.name).toBe('Jane Doe');
    });
});