Tech

Diary

Lecture

About Me

개발중

FE 테스트 개요

JeongSeulho

2023년 12월 21일

준비중...
클립보드로 복사

0. 들어가며

테스트란 무엇이며 왜 필요한지, 테스트 작성 규칙에 대해 정리

1. 테스트란 무엇인가?

애플리케이션의 품질과 안정성을 높이기 위해 사전에 결함을 찾아내고 수정하기 위한 행위
주로 특정 모듈(특히 컴포넌트)이 사양에 잘 동작하는지 자동화된 테스트로 검증

2. 테스트의 효과

(1) 좋은 설계를 이끌어낸다

1개의 페이지를 나누지않고 1개의 컴포넌트로 만들었다고 가정하자, 이에대한 테스트 코드를 작성하면 어떤 문제가 있을까

  1. 특정 기능만 따로 검증하기 어렵다
  2. 복잡한 구조로 테스트 누락이 발생할 수 있다
  3. 간단한 수정사항에도 얽혀있는 다른 기능들까지 테스트를 해야한다

이러한 문제들로 쉬운 테스트 작성을 위한 설계를 고민하게 되고 이는 좋은 설계를 이끌어낸다

(2) 안정적인 리팩토링

리팩토링이란 결과의 변경없이 코드의 구조를 재조정하는 것을 말한다.
리팩토링 과정에서 테스트 코드가 있다면 변경된 코드가 기존의 기능을 깨뜨리지 않았는지 쉽게 확인하며 안정성있고 자신감있게 리팩토링을 진행할 수 있다.

(3) 애플리케이션의 이해를 높이는 문서

테스트 코드는 애플리케이션의 기능을 상세히 설명하는 문서 역할을 한다.

3. 올바른 테스트 작성을 위한 규칙

(1) 인터페이스를 기준으로 테스트

🙅 bad case

copy
it('isShowModal 상태를 true로 변경하면 "안녕하세요"가 출력된다', () => {
  SpecificComponent.setState({ isShowModal: true });
  ...
});

위와 같이 상태를 직접 변경하는 테스트의 문제점은 다음과 같다.

  1. 변경되는 상태가 많다면 일일이 직접 변경해야한다
  2. 어떤 것을 검증하는지 한눈에 알아보기 어렵다
  3. 구현에 종속되어 상태나 변수명이 바뀌면 테스트 코드를 모두 수정해야한다

🙆 good case

copy
it('버튼을 클릭하여 모달을 띄운다', () => {
  const button = SpecificComponent.getByText('버튼');
  fireEvent.click(button);
  ...
});

DOM 이벤트 핸들러라는 인터페이스를 기준으로 테스트를 작성하면

  1. 내부 구현과 종속되지 않는다
  2. 어떤 행위를 검증하는지 한눈에 알아보기 쉽다

(2) 커버리지 보다는 의미있는 테스트인지 고민

커버리지란 테스트 코드가 얼마나 많은 코드를 검증하는지를 나타내는 지표이며 %로 표현한다.
100%를 위하여 의미없는 테스트를 작성하는 것은 좋지 않다.

다음과 같이 간단히 배열을 받고 리스트로 리턴하는 컴포넌트가 있다고 가정하자

copy
const List = ({ items }) => {
  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
};

이러한 컴포넌트에 테스트는 의미가 없다.

마찬가지로 이런 간단한 로직의 유틸 함수에 테스트는 의미가 없다.

copy
export const isNumber = (num) => typeof num === "number";

커버리지 100%를 위해 검증하지 않고 이 테스트에 어떤 의미가 있는지 고민하자

(3) 테스트 코드의 가독성 높이기

테스트도 유지보수가 필요하며 가독성이 높은 테스트 코드는 유지보수가 쉽다.

1. 테스트 하고자하는 내용을 명확히 적자

copy
// 🙅 bad case

it('리스트에서 항목을 삭제한다.', () => {
  ...
});

// 🙆 good case
it('항목들을 체크한 후 삭제 버튼을 눌러 리스트의 체크된 항목들을 삭제한다', () => {
  ...
});

2. 하나의 테스트에는 하나의 동작만 검증하자

copy
// 🙅 bad case
it('장바구니에 담긴 상품들이 노출되고, 수량을 변경하면 가격이 재계산된다', () => {
  ...
});

// 🙆 good case
it('장바구니에 담긴 상품들이 노출된다', () => {
  ...
});
it('장바구니에 담긴 수량을 변경하면 가격이 재계산된다', () => {
  ...
});

4. AAA 테스트 패턴

  • Arrange : 테스트를 수행하기 위한 환경 만들기(컴포넌트 렌더링)
  • Act : 테스트할 동작 시뮬레이션(이벤트 발생 시키기, 함수 실행하기)
  • Assert : 기댓값과 실제값을 비교하여 테스트 검증하기