<aside> 💻

feature/test 브랜치 작업 내역

이 브랜치에서는 React 컴포넌트에 대한 효율적인 테스트 구현을 위해 다음과 같은 계획을 수립했습니다:

1. 개발 환경 설정

  1. Jest 및 관련 패키지 설치

    npm install -D jest @types/jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom
    
  2. TypeScript 설정 파일 구성

  3. Jest 환경 설정 파일 생성

2. 테스트 대상 컴포넌트

  1. 사용자 인증 관련
  2. 기능 컴포넌트

3. 테스트 범위

  1. 컴포넌트 렌더링 검증
  2. 사용자 인터랙션 테스트
  3. 비동기 작업 처리 확인
  4. 에러 핸들링 검증

4. 테스트 파일 구조

src/
├── components/
│   ├── auth/
│   │   └── __tests__/
│   │       └── LoginForm.test.tsx
│   └── auth/
│       └── __tests__/
│           └── RegisterForm.test.tsx
├── pages/
│   ├── __tests__/
│   │   └── TodoListPage.test.tsx 

</aside>

구현 상세 가이드

1. Jest 기반 유닛 테스트 코드 작성

  1. jest 설정(라이브러리 설치):
npm install -D jest @types/jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom
  1. tsconfig.test.json 생성:
{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "types": ["node", "jest", "@testing-library/jest-dom"],
    "module": "CommonJS",
    "moduleResolution": "Node",
    "esModuleInterop": true,
    "allowJs": true,
    "jsx": "react-jsx"
  },
  "include": ["src", "**/*.test.ts", "**/*.test.tsx", "jest.setup.ts"]
}
  1. jest.config.ts 생성:
/** @type {import('jest').Config} */
module.exports = {
  preset: "ts-jest",
  testEnvironment: "jest-environment-jsdom",
  transform: {
    "^.+\\\\.(ts|tsx)$": ["ts-jest", {
      tsconfig: "tsconfig.test.json"
    }]
  },
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1",
    "\\\\.(css|less|sass|scss)$": "identity-obj-proxy"
  },
  setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
  testMatch: ["<rootDir>/src/**/*.test.{ts,tsx}"],
  moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
  testEnvironmentOptions: {
    customExportConditions: ['']
  }
};
  1. package.json에 test 스크립트 추가:
{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch"
  }
}
  1. jest.setup.ts 생성:
/// <reference types="@testing-library/jest-dom" />
import '@testing-library/jest-dom';
import { TextEncoder, TextDecoder } from 'util';

declare global {
  interface JestMatchers<R> {
    toBeInTheDocument(): R;
    toHaveClass(className: string): R;
  }
}

if (!globalThis.TextEncoder) {
  Object.defineProperty(globalThis, 'TextEncoder', {
    value: TextEncoder,
    writable: true,
    configurable: true,
  });

  Object.defineProperty(globalThis, 'TextDecoder', {
    value: TextDecoder,
    writable: true,
    configurable: true,
  });
}

export {};

이렇게 기본 설정을 하고, 첫 테스트 파일을 작성합니다.

2. 컴포넌트 2회 이상 테스트

1. 컴포넌트 테스트 구조

1) TodoListPage 테스트

// src/pages/__tests__/TodoListPage.test.tsx
describe("TodoListPage", () => {
  it("renders todo list correctly", async () => {
    renderWithProviders(<TodoListPage />);
    
    // 로딩 상태 확인
    expect(screen.getByText(/loading/i)).toBeInTheDocument();
    
    // 데이터 로드 후 상태 확인
    await waitFor(() => {
      expect(screen.getByText("Test Todo 1")).toBeInTheDocument();
      expect(screen.getByText("Test Todo 2")).toBeInTheDocument();
    });
  });

  // Todo 완료 상태 테스트
  it("displays completed status correctly", async () => {
    renderWithProviders(<TodoListPage />);
    await waitFor(() => {
      const completedTodo = screen.getByText(/Test Todo 2/);
      expect(completedTodo).toHaveClass("line-through");
    });
  });
});

테스트 포인트: