jinseok.choi
7 min readFeb 10, 2018

--

Jest를 이용한 Unit Test 적용기

어떻게 테스트를 진행해야 할까요?

처음 프론트엔드 테스트라는 것을 알게된 것은 3년전 Angular 1을 공부하면서였다. 그 때는 이게 머지? 개발하기도 바쁜데 꼭 필요한가? 라는 생각에 간단히 훑어보고 지나갔었다. 왜 그때 공부하지 않았는지 열심히 후회하고있는 중이지만 지금부터라도 공부를 시작하자는 생각에 현재 프로젝트에 React 를 사용하니 Jest를 사용하여 단위테스트를 시작하기로 정했다.

Jest란?

Jest는 페이스북에 만든 테스트 프레임워크이다. 빠르게 설치하고, 테스트하기에는 좋은 것 같다. 내가 느끼기에 가장 좋았던 것은 Snapshot이다. 실제 브라우저에 내가 원하는데로 랜더링 되는지 판단할 수 있는 것은 아주 매력적이었다. 다만 실제 브라우저가 아닌 가상환경에서 실행되는 것이기 때문에 UI와 관련된 부분을 많이 대체해야하기 때문에 테스트하기 어렵게 느껴졌다.

빠르게 Jest를 설치하고, 테스트를 실행해보자.

Nodejs가 설치 되었다면, 빠르게 테스트를 진행할 수 있다. 만약 설치 되어있지 않다면, nodejs 사이트를 방문하여 설치 후 아래의 명령어를 터미널에서 실행하자.

npm init -y
npm install --save-dev jest

그 후 package.json 파일에서 scripts 프로퍼티에 명령어를 추가하자.

// package.json{
...
"scripts": {
"jest": "jest"
}
...
}

그 후 test/sample.spec.js 파일을 만들어보자.

// test/sample.spec.jstest('This is a sample', () => {
expect(true).toBe(true);
});

파일을 생성후 터미널에서 명령어를 실행하면, 테스트과 통과된 결과를 볼 수 있다.

npm run jest

단위테스트를 작성하는 이유?

내가 단위테스트를 시작한 이유는 주위에서 너도나도 단위테스트를 해야한다는 말도 들어서이지만 가장 큰 이유는 내가 작성한 코드가 잘 동작 하는지 확인하기 위해 시작했다.

예를 들면, 카페에서 고객에게 커피를 주문받고, 커피를 내리고, 고객에게 전달해야한다고 생각해보자. 단위테스트를 작성하지 않는다면, 동작여부를 브라우저에서 테스트를 해야하고, 커피를 주문받는 과정에서 예상치 못한 에러가 발생하면, 그 다음 과정은 진행하지도 못한다. 그리고 예제처럼 단순한 과정이 아니라 복잡한 과정에서 에러가 발생한다면 디버깅을 하는데도 많은 시간을 투자해야한다. 하지만 단위테스트는 기능이 정확히 동작 하는지 확인하고, 테스트 통과된 기능을 조합하여 하나의 또 다른 기능을 구현하기 때문에 기능의 정확한 동작여부 체크 및 디버깅을 쉽게 도와준다.

단위테스트 작성하기 전 규칙을 정하자.

단위테스트를 작성할 때는 다음과 같은 규칙을 지켜야한다.

  • 독립적(Independent)이어야한다. 어떤 테스트도 다른 테스트에 의존하지 않아야한다.
  • 격리(Isolation)되어야한다. Ajax, LocalStorage, UI Event 등 테스트 대상이 의존하는 것을 다른 것으로 대체한다. 이렇게 대체하는 것을 테스트 더블(Dummy, Stub, Fake, Spy, Mock)이라고 한다.
  • given, when, then 단계에 따라 테스트 코드를 작성한다.

단위테스트 시나리오를 작성하자.

단위테스트를 하며 가장 어려웠던 것은 시나리오를 작성하는 것 이었다. 시나리오가 있어야 테스트를 진행할 수 있기 때문에 가장 중요했다.

팀프로젝트에 적용하기 전에 우선 간단하게 슬라이드를 좌우로 이동 시킬수 있는 Swiper 컴포넌트를 만들어봤다. 이름은 거창하지만 단순하게 이전 슬라이드, 다음 슬라이드로 이동할 수 있는 컴포넌트이다.

사용자는 Swiper 라이브러리를 사용하는 개발자라고 가정했다.

우선 사용자의 스토리를 정의했다.

Story. 사용자는 Swiper를 생성할 수 있다.
Story. 사용자는 다음 슬라이드로 이동할 수 있다.
Story. 사용자는 이전 슬라이드로 이동할 수 있다.

Swiper 라이브러리는 간단하기 때문에 3개의 스토리를 정의했다. 스토리는 당장 개발 해야할것 만 정의할 필요는 없다. 추후 개발할 것을 미리 정의하고, 표시만 해두면 된다. 이 스토리는 사용자와 대화하고, 기능을 추적하는데 많은 도움을 준다.

스토리가 정의 되었다면, 스토리에 대한 테스트 스펙을 정의하자.

Story. 사용자는 Swiper를 생성할 수 있다.
senario
given: 설정없이
when: Swiper를 생성하면
then: default 속성을 가진 Swiper를 생성한다.
senario
given: width와 height을 설정하고
when: Swiper를 생성하면
then: 설정된 width와 height을 가진 Swiper를 생성한다.
Story. 사용자는 다음 슬라이드로 이동할 수 있다.
senario
given: 다음 슬라이드가 있을 때
when: 다음 슬라이드를 요청하면,
then: 다음 슬라이드로 이동한다.
senario
given: 다음 슬라이드가 없을 때
when: 다음 슬라이드를 요청하면,
then: 현재 슬라이드를 유지한다.
Story. 사용자는 이전 슬라이드로 이동할 수 있다.
senario
given: 이전 슬라이드가 있을 때
when: 이전 슬라이드를 요청하면,
then: 이전 슬라이드로 이동한다.
senario
given: 이전 슬라이드가 없을 때
when: 이전 슬라이드를 요청하면,
then: 현재 슬라이드를 유지한다.

스토리와 스펙을 이용하여 테스트 코드와 React Swiper 컴포넌트를 작성하면 아래와 같이 작성된다.

Swiper.spec.jsx
Swiper.jsx

‘시나리오 작성 -> 테스트 코드 작성 -> 기능 구현 -> 리팩토링’ 이 과정을 반복적으로 가지며 중복되는 코드를 제거하고, 기능을 분리한다.

실제로는 이렇게 간단히 테스트가 끝나진 않는다. 대부분의 코드는 의존적이기 때문에 테스트 더블(Dummy, Stub, Fake, Spy, Mock)이 필요하다. 테스트 더블은 실제코드를 대체하는 것을 말한다. 이 내용은 추후에 더 공부하며 작성해볼 예정이다.

앞으로는…

단위테스트를 하는 것은 귀찮고, 변경시 많은 부분을 수정해야하는 경우가 발생할 수도 있다. 하지만 의존적이지 않기 때문에 자유롭게 부시고, 다시 만들 수 있었다. 그리고 분명한 것은 테스트 코드를 작성하지 않았을 때보다 테스트 코드를 작성하고 있는 지금이 전보다 훨씬 나은 코드라는 것이다.

앞으로 계속 단위테스트를 진행하며, 테스트하는 습관을 들이고, 더 재미있는 것을 만들어볼 생각이다. 우선 모방부터.

--

--