🧪 프론트엔드 테스팅 입문

Jest와 React Testing Library를 활용한 컴포넌트 테스트 작성법을 학습합니다

컴포넌트 렌더링 테스트

컴포넌트가 올바르게 렌더링되는지 확인

컴포넌트 코드:

// Button.tsx
interface ButtonProps {
  onClick: () => void;
  children: React.ReactNode;
  disabled?: boolean;
}

export const Button = ({ onClick, children, disabled }: ButtonProps) => {
  return (
    <button 
      onClick={onClick} 
      disabled={disabled}
      className="px-4 py-2 bg-blue-500 text-white rounded"
    >
      {children}
    </button>
  );
};

테스트 코드:

// Button.test.tsx
import { render, screen } from '@testing-library/react';
import { Button } from './Button';

describe('Button 컴포넌트', () => {
  test('버튼이 올바르게 렌더링되어야 한다', () => {
    render(<Button onClick={() => {}}>클릭하세요</Button>);
    
    const button = screen.getByText('클릭하세요');
    expect(button).toBeInTheDocument();
  });

  test('disabled 상태일 때 버튼이 비활성화되어야 한다', () => {
    render(<Button onClick={() => {}} disabled>클릭하세요</Button>);
    
    const button = screen.getByText('클릭하세요');
    expect(button).toBeDisabled();
  });
});

사용자 상호작용 테스트

클릭, 입력 등 사용자 이벤트 테스트

컴포넌트 코드:

// Counter.tsx
import { useState } from 'react';

export const Counter = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>현재 카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>증가</button>
      <button onClick={() => setCount(count - 1)}>감소</button>
      <button onClick={() => setCount(0)}>리셋</button>
    </div>
  );
};

테스트 코드:

// Counter.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Counter } from './Counter';

describe('Counter 컴포넌트', () => {
  test('증가 버튼 클릭 시 카운트가 증가해야 한다', async () => {
    const user = userEvent.setup();
    render(<Counter />);
    
    const increaseButton = screen.getByText('증가');
    const count = screen.getByText(/현재 카운트:/);
    
    expect(count).toHaveTextContent('현재 카운트: 0');
    
    await user.click(increaseButton);
    expect(count).toHaveTextContent('현재 카운트: 1');
    
    await user.click(increaseButton);
    expect(count).toHaveTextContent('현재 카운트: 2');
  });

  test('리셋 버튼 클릭 시 카운트가 0이 되어야 한다', async () => {
    const user = userEvent.setup();
    render(<Counter />);
    
    const increaseButton = screen.getByText('증가');
    const resetButton = screen.getByText('리셋');
    
    await user.click(increaseButton);
    await user.click(increaseButton);
    await user.click(resetButton);
    
    expect(screen.getByText(/현재 카운트:/)).toHaveTextContent('현재 카운트: 0');
  });
});

🚀 테스트 실행

💡 테스팅 베스트 프랙티스

좋은 테스트의 특징

  • 빠른 실행: 빠른 피드백 루프
  • 독립적: 다른 테스트에 영향받지 않음
  • 반복 가능: 항상 같은 결과
  • 자체 검증: 명확한 성공/실패
  • 시기적절: 코드와 함께 작성

테스트 작성 팁

  • • 구현이 아닌 동작을 테스트
  • AAA 패턴 사용 (Arrange-Act-Assert)
  • • 테스트 이름은 명확하고 구체적으로
  • 엣지 케이스도 테스트
  • • 테스트 코드도 유지보수 고려

🛠️ 주요 테스팅 도구

Jest

JavaScript 테스트 러너, 모킹, 스냅샷 테스트 지원

React Testing Library

사용자 관점의 React 컴포넌트 테스트

Cypress

브라우저 기반 E2E 테스트 프레임워크

🧑‍💻

1nnovator 김민성

JavaScript 학습 센터 개발자

기술 블로그Interactive JavaScript Learning Platform

🌟 이 프로젝트가 도움이 되셨다면 블로그에서 더 많은 개발 이야기를 확인해보세요!

🤖이 페이지는 생성형 AI의 도움을 받아 제작되었습니다.