[React] React Testing



본 문서에서는 리액트 프로젝트에서 TDD (Test Driven Development)를 하는 방법에 대해 요약함. (velopert님의 문서 참조)

TEST 란?

우리가 작성한 코드가 잘 작동한다는 것을 검증하는 작업을 의미.

우리가 만든 프로젝트의 모든 기능을 사람이 수동으로 하나하나 확인하는 것은 정말 번거로운 일이기 때문에, 테스트 자동화라는 작업을 함.

사람이 직접 확인을 하는 것이 아니라 테스트를 하는 코드를 작성해서, 테스트 시스템이 자동으로 확인을 해줄 수 있게 함.

TEST 자동화를 통해 얻을 수 있는 이점

테스트 코드를 사용하면 프로젝트를 개발하는 과정에서 우리가 써내려가는 코드가 기존의 기능들을 실수로 망가뜨리는 것을 효과적으로 방지 할 수 있다.

실제 발생할 수 있게 되는 상황에 대해 미리 정해놓고 그에 맞춰 코드를 작성하게 되면 우리가 실수로 빠뜨릴 수 있는 사항들을 까먹지 않고 잘 챙길 수 있게 됩니다.

코드를 리팩토링 할 때 좋다. 리팩토링 이후에는 버그가 있는지 없는지 정말 세밀하게 확인을 해야할 때, 테스트 코드가 존재한다면, 이전과 똑같이 작동하는지 검증하는게 매우 쉬워지기 때문에 코드의 질을 향상시키는 것에 도움이 된다.

테스트 코드를 작성한다고 해서 프로젝트에서 버그가 발생하지 않는 것은 아니다. 테스트 코드를 작성해도, 프로젝트에는 버그가 발생할 수 있다.

하지만, 만약 버그가 발생했더라면, 그 버그를 고치고 나서, 버그가 발생하는 상황에 대한 테스트 코드를 작성해두면, 두번 다시 똑같은 실수를 하는 것을 방지할 수 있다.

TEST 종류

테스트 코드는 크게 두 종류로 나눠짐.

유닛 테스트

유닛 테스트는 아주 조그마한 단위로 작성됨.

EX)

  1. 컴포넌트가 잘 렌더링된다.
  2. 컴포넌트의 특정 함수를 실행하면 상태가 우리가 원하는 형태로 바뀐다.
  3. 리덕스의 액션 생성 함수가 액션 객체를 잘 만들어낸다.
  4. 리덕스의 리듀서에 상태와 액션객체를 넣어서 호출하면 새로운 상태를 잘 만들어준다.

통합 테스트

기능들이 전체적으로 잘 작동하는지 확인하기 위해서 사용하는 것.

EX)

  1. 여러 컴포넌트들을 렌더링하고 서로 상호 작용을 잘 하고 있다.
  2. DOM 이벤트를 발생 시켰을 때 우리의 UI에 원하는 변화가 잘 발생했다.
  3. 리덕스와 연동된 컨테이너 컴포넌트의 DOM 에 특정 이벤트를 발생시켰을 때 우리가 원하는 액션이 잘 디스패치 된다.

유닛 테스트는 하나에 초점을 둔다면,

통합 테스트는 여러 요소들을 고려하여 작성함.

유닛 테스트는 보통 한 파일만 불러와서 진행하는 반면,

통합 테스트는 여러 요소들을 고려하는 과정에서, 여러 파일들을 불러와서 사용 될 수도 있다.
(한 파일에 있는 여러 기능들을 함께 사용하는 것도 통합 테스트로 간주됨.)

JavaScript Testing 기초

자바스크립트로 작성된 프로젝트에 테스트 자동화를 사용 할 때 사용 할 수 있는 도구는 다양하다.

  • Karma
  • Jasmine
  • Jest
  • Chai
  • Mocha

위 도구들은 비슷한 작업을 처리하지만 각각 다른 특성들을 가지고 있다.

** 해당 글에서는 Jest를 사용함.

Jest

Jest는 Facebook에서 Jasmine기반으로 만든 테스팅 프레임워크이다.

Jest 예제

// 참조

TDD 란?

Test Driven Development (테스트 주도 개발)

테스트가 개발을 이끌어 나간는 형태의 개발론

선 테스트 코드 작성, 후 구현

TDD의 3가지 절차

1. 실패

실패하는 테스트 케이스를 먼저 만들라는 것.

실패하는 테스트 케이스를 만들 때는 프로젝트의 전체 기능에 대하여 처음부터 모든 테스트 케이스를 작성하는 것이 아니라,

지금 가장 먼저 구현할 기능 하나씩 테스트 케이스를 작성함.
(상황에 따라 한번에 여러 테스트 케이스를 작성하기도 함.)

2. 성공

실패하는 테스트 케이스를 통과시키기 위하여 코드를 작성하여 테스트를 통과시키는 것

3. 리팩토링

우리가 구현한 코드에 중복되는 코드가 있거나, 혹은 더 개선시킬 방법이 있다면 리팩토링을 진행함.

리팩토링을 진행하고 나서도 테스트 케이스가 성공하는지 확인함.

이 절차가 끝났다면, 다시 첫번째 절차로 돌아가서 다음 기능 구현을 위하여 새로운 실패 테스트 케이스를 작성함.

TDD의 장점

TDD를 진행하면서 테스트 케이스를 작성할 때 주로 작은 단위로 만들기 때문에,
코드를 작성 할 때 코드가 너무 방대해지지 않고, 코드의 모듈화가 자연스럽게 잘 이루어지면서 개발이 진행됨.

TDD를 하면 자연스레 테스트 커버리지가 높아질 수 밖에 없다.테스트를 먼저 작성을 하고 구현을 하기 떄문이다.
테스트 커버리지가 높아지면 결국 리팩토링도 쉬워지고 유지보수도 쉬워진다.
결국 퀄리티를 높이기에 좋은 환경이 구성된다.

버그에 낭비하는 시간도 최소한으로 할 수 있고 우리가 구현한 기능이 요구사항을 충족하는지 쉽게 확인 할 수 있다.

TDD 연습

// 참조

React Test

리액트 컴포넌트를 테스트 할 때에는 주로 어떠한 결과가 화면상에 잘 나타났는지,
그리고어떠한 이벤트 혹은 함수가 호출 됐을 때 원하는 업데이트가 잘 반영이 되는지를 확인합니다.

이를 수행하는 가장 기본적인 방법은 react-dom/test-utils 안에 들어있는 유틸 함수를 사용하는 것이다.

그런데, 위 유틸 함수들을 직접 사용해서 테스트 코드를 작성하는건 불가능한건 아니지만 조금 복잡하고, 불편한 점들이 있기 때문에,

테스팅 라이브러리를 사용하는 것을 리액트 공식문서에서도 권장하고 있다.

테스팅 라이브러리 종류

  1. Enzyme
  2. React-testing-library

리액트 공식문서에서 사용을 권장하는 라이브러리는 react-testing-library 이다.

그리고, 대체 방안으로 Enzyme가 있다고 언급하고 있다.

예전에는 airbnb에서 만든 Enzyme를 사용하는 것이 가장 좋은 솔루션이었는데, 요즘은 react-testing-library가 많은 주목을 받고 있다.

Enzyme의 경우엔 15년에 개발되었고, react-testing-library의 경우엔 18년부터 개발이 되어 18년 말부터 급부상을 하고 있다.

Enzyme vs React-testing-library

사용률만 따지면 Enzyme가 높다. Enzyme와 react-testing-library는 서로 다른 철학을 가지고 있다.

Enzyme

Enzyme를 사용하여 테스트 코드를 작성 할 때에는 컴포넌트의 내부 기능을 자주 접근한다.

예를 들어 컴포넌트가 지니고 있는 props, state를 확인하고, 컴포넌트의 내장 메소드를 직접 호출하기도 한다.

React-testing-library

react-testing-library는 반면 렌더링 결과에 조금 더 집중을 한다.

실제 DOM에 대해서 신경을 더 많이 쓰고, 컴포넌트의 인스턴스에 대해서 신경을 쓰지 않고, 실제 화면이 무엇이 보여지는지, 그리고 어떠한 이벤트가 발생했을 때 화면에 원하는 변화가 생겼는지 이런 것을 확인하기에 조금 더 최적화 되어있다.

그래서, react-testing-library 는 조금 더 사용자의 관점에서 테스팅하기 더욱 용이하다.

Enzyme 테스트

// 참조

React-testing-library 테스트

// 참조

참고 문서

https://velog.io/@velopert/react-testing

https://velog.io/@velopert/TDD%EC%9D%98-%EC%86%8C%EA%B0%9C