Jest #1 - Intro

Joshua Song / 송성현·2020년 3월 11일
6

백엔드

목록 보기
3/8

Introduction

개인적으로 Test Case 를 작성해보고 싶어서 Jest를 공부하기로 마음 먹었다. Jest에 익숙해져야, 테스트케이스도 궁극적으로 작성할 수 있기 때문이다. Chai도 있고 Mocha도 있지만 프런트도, 백도 테스트케이스 작성을 할때 자주 사용하는 Jest로 시작하는게 좋을 것 같다 충고를 받아서 Jest에 대해 기본적인 개념을 갖춘 뒤, 간단하게 코드 작성을 통해 익혀보기로 했다.

Introduction: What is Jest?

공식문서(https://jestjs.io/)에 따르면, Jest는 자바스크립트를 위한 간단함에 강점이 있는 테스팅 프레임워크이다. 참고로 페이스북에서 만든 오픈 자바스크립트 테스팅 라이브러리이고 "Delighful JavaScript Testing" 이라는 슬로건을 가지고 있다. 리액트와 리액트 네이티브와 같이 사용하면 좋다고 한다. Jest는 Babel, TypeScript, Node, React, Angular 와 Vue 같은 프로젝트와 사용이 가능하다. 테스트케이스를 통해 코드가 올바른 기능을 하는지 체크가 가능하다. 테스트케이스? Jest!

Advantage

1. Jest는 설치하기 쉽다!

  • Jest는 npm 혹은 yarn을 사용해 직접적으로 설치할 수 있다.
  • package.json의 script를 추가하면 저절로 test.js 파일을 모두 실행한다.

2. Jest는 빠르다!

  • Jest의 빠른 속도는 테스트가 CPU에 한정될 경우 매우 유리하다.

  • Airbnb는 Mocha에서 Jest로 테스트 프레임워크를 바꿨는데 테스트 런타임이 12분 이상 줄었다.

  • Jest 가 빠른 이유는 여러 복합적인 요소들 덕분이다.
    - 병렬 프로그래밍

    • 가장 느린 테스트를 먼저 실행한다. 이로서 코어들 최대한 활용한다.
    • Babel 변환을 캐싱해놓는다. CPU를 많이 잡아먹는 바벨 변환을 줄인다.

    3. Jest는 필요한 것을 갖추고 있다!

  • Jest는 광범위한 모의 라이브러리를 갖추고 있어 내부적으로 보유하고 있는 기능이 있다.

  • 원래는 Jasmine 기반이었지만, 최근 버전에는 분리가 되면서 Jasmine의 이점들을 모두 상속 받아 같은 기능을 갖추면서도 Jest 고유의 특성으로 더욱 성능을 향상시켰다.

    4. Jest는 모킹하는 능력이 뛰어나다!

  • 모킹 (Mocking, 모의로 기능을 구현하는 것)은 유닛테스팅의 중요한 부분인데, 빠른 테스트를 원한다면 매우 중요하다.

  • 모킹은 관련없고 느린 디펜던시를 대체하기에 Jest는 모킹을 통해 디펜던시를 컨트롤하고 걸리는 시간을 향상시킬 수 있다.

    단순 모의 함수

    • 디펜던시의 기능을 흉내내는 것은 단위 테스트의 특징인데, 코드가 파일을 읽던, 작성하던, 데이터베이스 접근을 위해 원격 서비스를 호출하던, 테스트의 구성이 복잡하고 시간이 오래 걸릴 수 있다. 병렬 프로그래밍의 경우, 적절하게 컨트롤 하는 것이 어려울 수 도 있다.
    • 이러한 경우, 실제 디펜던시를 로그만 기록하는 mock 함수로 대체하면 workflow를 따라갈 수 있고 호출 횟수와 어떤 인자가 들어갔는지 볼 수 있다. jest.fn()을 사용하면 된다.

    Manual Module Mocks

    • 간혹, 모듈과 데이터 전부를 대체해야하는 경우가 있는데, Jest는 mocks sub-directory에 있는 사용자 고유의 모듈로 (있다면) 대체한다.
    • 코드가 그런 모의 모듈을 사용했을 시, 실제 모듈이 아닌 모의 모듈을 사용한다. 그래서 실제 모듈을 사용하고 싶으면 jest.Unmock('moduleName')을 사용한다.

    Timer Mocks

    • 시간은 단위 테스트의 가장 중요한 요소 중 하나이다.

    • Jest는 여러 시간에 관련된 함수를 통해 시간을 컨트롤 하는데 도움을 준다.

      - setTimeout()
      - setInterval()
      - clearTimeout()
      - clearInterval()

      ES6 Class Mocks

    • Jest는 ES6 클래스를 지원하고, 흉내내는 다양한 방법이 있다.

  • Autmoatic mock: constructor와 모든 method를 흉내. 하지만 undefined 반환.

  • Manual mock: 사용자 고유의 모의 함수.

  • 클래스 공장을 흉내낸다.

  • mockImplementation() 혹은 mockImplementationOnce()를 사용한 선택적 흉내

5. Jest는 TypeScript를 지원한다!

  • ts-jest package를 사용하면 타입스크립트를 사용할 수 있다.

6. Jest는 커버리지를 효과적으로 처리한다. 그리고 쉽다!

  • Jest는 내장 커버리지 리포트를 가지고 있다. 코드의 80%만 테스트하면 나머지 20%의 버그는 생산 과정에서만 발견된다.
  • 비지니스 관점에서, 어떤 특정 부분의 시스템을 위한 테스트를 건너뛸 수도 있다. 하지만, 이것은 상황에 따라 달라질 수 있기에 시스템의 각 파트들이 얼마나 테스트 적용 범위를 정확히 볼 수 있어야 한다.

7. Jest는 스냅샷을 사용한다!

  • Snapshot 테스트는 훌륭하고 효과적이다!
  • 스냅샷을 이용해 UI에 어떤 부분이 바뀌었는지 비교할 수 있다.
  • 스냅샷을 통해 객체의 현재 상태가 이전에 저장된 상태와 다른지 비교할 수 있다.

8. Jest는 Watch를 사용해 델타 테스팅을 할 수 있다!

  • Jest는 Watch 모드를 사용해 코드를 바꿀 때마다 자동으로 테스트를 실행할 수 있다.

Application

자, 그럼 장점을 어느정도 알아봤으니 이제 공식문서를 보면서 Jest에 입문하자!
처음이기에, Javascript로 진행한다. 이후 TypeScript로 넘어갈 생각이다.

설치

먼저 jest는 package.json이 있어야 설치가 되니, npm init 혹은 yarn init으로 하나 만들어 준 후,

yarn add --dev jest 

npm install --save-dev jest

둘 중 하나로 jest를 설치해준다. 개인적으로 난 공식문서가 다 yarn을 사용하길래 yarn으로 설치했다.

Applying Babel
Jest는 안타깝게도 ES5까지 자동적으로 인식하고, ES6를 사용하려면 Babel을 사용해 변환해주어야 한다.

yarn add --dev babel-jest @babel/core @babel/preset-env

이렇게 바벨을 설치해 준 후, babel.config.js라는 파일을 만들어, 그 안을 다음으로 채워준다.

// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current',
        },
      },
    ],
  ],
};

이렇게 설치를 해준다면, ES6 문법도 이제 사용 가능하다!

Jest Script 수정

"scripts": {
    "test": "jest",
    "testwatch": "jest --watchAll"
  },

Jest를 이용해 테스트를 돌린다면, script에 명령어를 추가해줘야 한다. 개인적으로 test라는 키워드에 "jest"를 실행해 주었고, testwatch라는 키워드에 "jest --watchAll"을 실행해 주었다. 이제 test 키워드를 실행할 경우, .test.js 파일을 자동적으로 찾아 실행해 준다. testWatch 키워드는, jest의 watch 기능을 사용하는 것인데 코드가 수정될 경우 바로 그 변경을 반영해 테스트를 실행해준다.

이제 직접 코드를 짜보자!

sum.js

일단 기본적으로 공식 사이트에 올라와있는 예제인 sum.js부터 실행해보았다.
1) sum.js 라는 파일과 sum.test.js 라는 파일을 생성해준다.

2) sum.js 파일을 채운다.

function sum(a, b) {
    return a + b;
  }
  export default sum;

간단한 함수이다. a와 b를 인자로 받아 더해준 후 반환한다. 이제 이 함수를 export 해줘야 테스트 함수에서 수입해 사용한다.

3) sum.test.js 파일을 채운다.

import sum from './sum';

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

이 테스트 코드는 먼저 미리 작성한 sum이라는 함수를 import 한다.
이후 test안에 들어가는 내용은 jest를 통해 테스트할 내용이다. "adds 1 + 2 to equal 3" 는 이 테스트가 증명하려고 하는, 테스트 하려고 하는 것을 설명해주는 것이고, expect 부분은 안에 테스트용으로 실험해볼 함수, 그리고 toBe는 나와야 하는 결과 값이다.

실제 작성한 sum 함수에 1과 2가 들어갔을 때 3이 결과값으로 나와 toBe안의 값과 일치하면 테스트가 통과되고, 일치하지 않는다면 통과되지 않을 것이다.

Actual Test

yarn test

앞에 작성한 sum.test.js를 실제로 테스트 해보자.
yarn test를 터미널에 치고 실험해보면...

성공이다!

그렇다면, 이번엔 sum.js 안의 함수를 오작동하게 고쳐보자.

function sum(a, b) {
  return a+b+2;
}
export default sum;

이렇게 2를 그냥 더해줘본후 테스트를 해보자.

친절하게 어떤 부분에서 틀렸는지, 무엇을 예상했지만 무엇을 받았는지까지 알려주고 틀렸다는 것을 알려준다. 친절...

yarn testWatch

이제, yarn testWatch기능을 테스트해보자. 아까와 같이 틀린 함수로 yarn testWatch를 실행하면...

이런식으로 위와 비슷한 틀린결과를 보이지만 끝나지 않았다는 것이 보인다. 그리고 옵션도 보여준다. 그러면 이제 sum.js의 코드를 원래대로 돌려놓아보자!

저절로 테스트가 통과되었다고 나온다.

이렇게 실시간으로 테스트의 진행사항을 보고 싶으면 testwatch를 켜놓아도 된다.

Conclusion

간단하게 Jest가 무엇인지, 장점이 뭔지, 또 어떻게 간단하게 사용하는지 정리해보았다.
실제 테스트 코드를 내가 조금이라도 직접 작성하니 신기하다. 조금 더 다양한 테스팅의 정리는 다음 포스트에 이어서 하기로 한다. 그럼 또 만나요~ 나 밖에 안보지만...ㅎ

참고
https://code.tutsplus.com/tutorials/8-things-that-make-jest-the-best-react-testing-framework--cms-30534
https://jestjs.io/docs/en/next/getting-started

profile
Grow Joshua, Grow!

2개의 댓글

comment-user-thumbnail
2020년 7월 9일

잘 보구 갑니다잇!

답글 달기

ㅋㅋㅋㅋㅋ 저도 보고 있습니다~

답글 달기