나도 테스트 코드 작성할래

Ryomi·2024년 8월 22일
3
post-thumbnail

바쁘다는 핑계로 테스트 코드 도입, 말만 1년째...
but, 혼자 공부해서 세미나 열어주겠어.

1. Jest 설치

npm install --save-dev jest

package.json에 테스트 스크립트 추가

{
  "scripts": {
    "test": "jest"
  }
}

vsCode를 사용하면 확장프로그램으로 jest를 깔면 npm test 말고,
더 편한 ui로 테스트를 실행해볼 수 있다.

2. Jest의 기본 문법

기본적으로 알아야 할 주요 함수는 describe, test (또는 it), expect입니다.

describetest
describe: 관련된 테스트를 그룹화할 때 사용합니다.
test 또는 it: 개별 테스트를 정의합니다.

//간단한 제목 
describe('간단한 숫자 계산', () => {
  //테스트 상세 설명
  test('2 더하기 2는 4', () => {
    expect(2 + 2).toBe(4);
  });

  test('2 곱하기 3은 6', () => {
    expect(2 * 3).toBe(6);
  });
});

2-1. It, Test의 차이점

test : 일반적으로 명확하게 “테스트를 정의한다”는 의미를 전달할 때 많이 사용됩니다.
it은 : “이것은 ~~한다”는 방식으로 자연스럽게 문장처럼 읽히도록 작성할 수 있어, 테스트의 의도를 보다 가독성 있게 표현할 때 유용합니다.

라고 지피티가 말해줬는데 뭔말인지 모르겠으니, 더 정리해보자.

// 두 방법은 완전히 동일하게 작성

test('2 더하기 2는 4', () => {
  expect(2 + 2).toBe(4);
});

it('2 더하기 2는 4', () => {
  expect(2 + 2).toBe(4);
});

2-2. BDD 스타일 테스트 = It, TDD 스타일 테스트= test

  • BDD 스타일 :
it("should do this thing", () => {});
it("should do the other thing", () => {});
  • TDD 스타일 :
test("if it does the other thing", () => {});
test("if it does the other thing", () => {});

근데 그냥 개취라서 맘에 드는거 쓰면 될 듯

3. 스파이(Spy)함수

  • 함수 호출 여부, 호출 횟수, 호출된 인자를 확인하고 싶을 때
const calculator = {
  add: (a, b) => a + b,
};

test('add 함수가 호출되었는지 확인', () => {
  const spy = jest.spyOn(calculator, 'add');
  calculator.add(1, 2);

  expect(spy).toHaveBeenCalled(); // 함수가 호출되었는지 확인
  expect(spy).toHaveBeenCalledWith(1, 2); // 특정 인자로 호출되었는지 확인

  spy.mockRestore(); // 스파이 함수 복원
});

4. Mock 함수와 Mocking

  • 외부 의존성을 제공하고, 특정상황에서 코드가 어떻게 동작하는지 테스트하려고 가짜데이터를 사용하는 기법
const fetchData = (callback) => {
  setTimeout(() => {
    callback('data received');
  }, 1000);
};

test('콜백 함수가 올바르게 호출되었는지 확인', () => {
  const mockCallback = jest.fn();

  fetchData(mockCallback);

  expect(mockCallback).not.toHaveBeenCalled(); // setTimeout 때문에 즉시 호출되지 않음
  jest.runAllTimers(); // 모든 타이머가 실행되도록 함

  expect(mockCallback).toHaveBeenCalledWith('data received');
});

4-1. 라이브러리 테스트 시 Mock 활용

  • 외부 라이브러리 의존성이 있는 경우, Jest의 jest.mock()을 사용해 라이브러리를 Mock할 수 있다.

어떤 .tsx 페이지에 라우터를 이동할 버튼이 use-navigate로 경로를 이동한다고 할 때를 예시로 들어보면

NavigationButton.jsx

import React from 'react';
import { useNavigate } from 'react-router-dom';

const NavigationButton = () => {
  const navigate = useNavigate();

  const handleClick = () => {
    navigate('/new-page');
  };

  return <button onClick={handleClick}>Go to New Page</button>;
};

export default NavigationButton;

테스트코드.jsx

// src/components/NavigationButton.test.js
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import { useNavigate } from 'react-router-dom';
import NavigationButton from './NavigationButton';

// useNavigate 훅을 Mock 처리
jest.mock('react-router-dom', () => ({
  useNavigate: jest.fn(),
}));

describe('네비 버튼 컴포넌트 ~~~', () => {
  test('누르면 /page 로 이동하게끔 ~~ ', () => {
    // Mock 함수 생성
    const mockNavigate = jest.fn();
    // Mock 함수 반환 설정
    useNavigate.mockReturnValue(mockNavigate);

    // 컴포넌트 렌더링
    const { getByText } = render(<NavigationButton />);

    // 버튼 클릭
    fireEvent.click(getByText('Go to New Page'));

    // navigate 함수가 '/page'로 호출되었는지 검증
    expect(mockNavigate).toHaveBeenCalledWith('/new-page');
  });
});

5. 어떤 것을 테스트해야 할까?

  • 단위 테스트(Unit Test): 함수나 컴포넌트의 개별 기능 테스트
  • 통합 테스트(Integration Test): 여러 모듈이나 컴포넌트 간의 상호작용 테스트
  • E2E 테스트(End-to-End Test): 사용자 시나리오에 기반한 전체 흐름 테스트

맘우리

일단 이렇게 간단하게 (안 간단한가 ,,) 알아보았는데,
React에서 Jest 외에도 여러 다른 테스팅 라이브러리를 사용할 수 있지만, 처음 접해본 Jest는 생각보다 훨씬 유용하다는 인상을 받았다.

또한, 테스트 우선순위를 명확히 정하고 중요 기능부터 차근차근 검증해 나가면서, 코드 품질을 한층 높일 수 있다는 점이 좋았다. Jest를 통해 더 안정적이고 유지보수하기 쉬운 코드를 작성하는 데 도움이 될 것 같네용. 굿!

테스트를 통해 코드의 신뢰성을 높이고, 개발 과정에서의 불확실성을 줄이는 것은 장기적으로 더 나은 소프트웨어 개발을 위한 중요한 과정임을 다시 한번 느꼈다.

테스트코드가 몸에 밸 수 있을 때까지 연습!

profile
making a list, checking it twice 🐥

0개의 댓글