Jest란 무엇인가?
jest는 페이스북에서 개발한 테스팅 라이브러리로써,
테스트 케이스 작성을 편리하게 해준다.
근데 테스트 케이스가 뭘까?
테스트케이스를 왜 쓰는지 알기 위해서는 TDD(테스트 주도 개발)의 개념에 대해 먼저 알아야 할 것이다.
TDD란 무엇인가?
TDD는 Test-Driven-Development의 약자로써, 한글로 번역하면 테스트 주도 개발이 되겠다.
테스트 주도 개발은 개발의 방법론 중 하나로써,
- 어떤 기능을 코딩하기 전에 그 기능의 입력, 출력값을 고려한 테스트 케이스를 먼저 작성한 후
- 테스트를 통과할 수 있는 코드를 작성하는 것을 말한다.
테스트 케이스부터 작성함으로써 얻는 통상적인 이점은 아래와 같다.
- 본격적으로 코딩하기전에, 프로그래밍이 어떻게 돌아가야 할 지를 우선적으로 생각하게 된다.
(무턱대고 코드부터 작성하게 될 시, 잘못된 방향성에 매몰되어 코드를 짜게될 수 있다.) - 파라미터값과 결과값을 미리 계산해서 테스트 케이스를 작성해야 하므로,
그 기능에 대한 이해도를 크게 높여 코드를 작성할 수 있다. (즉 생산성이 높은 코드를 작성할 수 있다.)
그렇다면, 테스트 케이스를 편리하게 작성하기 위한 툴인 jest를 사용해보자.
- 단, 이 게시물은 jest를 편하게 쓰기 위한 방법을 알려주는 것일 뿐, 모든 것을 담고있지는 않다.
- 그럼에도 불구하고, 이 게시물을 따라한다면 일단 jest를 이용한 테스트 케이스를 작성할 수 있다.
1. npm init
먼저, TDD를 적용할 폴더에 package.json을 만들어놓아야 한다.
package.json을 미리 생성해놓지 않는다면 대부분의 설치형 라이브러리를 사용할 수 없기 때문이다.
(또한, package.json의 환경설정을 통해 개발환경을 최적화 할 수 있는데,
이에 대해선 필요할때마다 구글링 할 수 있어야 하겠다.)
2. 명령 프롬프트(터미널)을 열고 jest를 전역(-g)에 설치한다.
전역 설정(-g)를 통해 라이브러리를 설치한다면 아래의 폴더에 라이브러리가 설치가 된다.
사용자폴더/....../AppData/Roaming/npm/node_modules
물론 jest를 굳이 전역에 설치하지 않아도 된다.
하지만 전역환경에 설치한다면, 단 한번의 설치로 모든 폴더에서 jest를 유연하게 사용할 수 있게 될 것이다.
다만 전역 설치가 '모든 상황에서' 옳다고 볼 수는 없다.
전역에 설치했을 때 이점이 더 크다면, 전역에 설치하는 것이고
개별 폴더에 설치했을 때 이점이 더 크다면 개별 폴더에 설치해야 한다.
3. 테스트 케이스 작성
package.json도 준비되었고, jest도 설치가 되었다면
이제부터는 테스트케이스를 작성할 수 있다.
위는 jest 라이브러리 문법을 통해 간단한 테스트 케이스를 작성한 것이다.
일단 테스트 코드 작성을 위해 jest의 몇가지 메서드를 알아보자.
- describe(문자열, 콜백함수) : 함수를 테스트하기 위해 만든 jest 메서드이다 테스트 케이스 여러개를 하나로 묶어주는 역할을 한다. 문자열에는 테스트 케이스의 설명이 들어가고, 콜백함수에는 it 메서드를 추가할 수 있다.
이때, describe의 콜백함수는 여러 개의 it 메서드를 가질 수 있다. - it(문자열, 콜백함수) : 실질적으로 테스트 케이스가 가져야할 인수를 파라미터에 넘겨주고, 결과값을 비교할 수 있는 기능을 가진 jest 메서드이다.
전달받은 함수를 호출한 리턴값을 변수에 담은 뒤, expect(변수).toEqual(기댓값) 메서드를 통해 테스트 케이스가 PASS인지 FAIL인지 판단할 수 있게된다.
const fn = require('./fn.js') // 의미: fn라는 변수에다가 fn.js에서 exports한 module객체를 추가한다.
describe('sumAll function', () => {
it('어레이 내 모든 엘리먼트 더하기', () => {
const result = fn.sumAll([10, 9, 8])
expect(result).toEqual(27)
})
})
/*
describe('테스트 케이스를 설명할 문자열', () => {
it('실제 테스트 케이스', () => {
const 실험함수출력값 = fn.실험할함수명(파라미터)
expect(실험함수출력값).toEqual(기댓값)
})
})
*/
중요한 것은 it 메서드의 expect(변수).toEqual(기댓값) 이다.
expect 메서드의 파라미터로 전달된 변수의 값이 toEqual 메서드의 파라미터로 전달된 기댓값과 같다면
테스트케이스는 PASS하게 되고, 같지 않으면 FAIL하게 된다.
위에서 작성한 테스트케이스는
어레이 내 모든 엘리먼트를 더하는 기능을 하는 함수에 대한 테스트 케이스이다.
따라서 배열 [10, 9, 8] 을 인수로 받게되면 27을 출력해야 한다. 그래서 위와 같은 테스트 케이스가 작성되었다.
여기에 추가로, 배열 속에 문자열을 넣었을 때를 고려하거나,
아무 인자도 넣지 않았을때의 출력값을 고려해볼 수도 있다.
2가지 케이스를 추가로 작성해보자.
const fn = require('./fn')
describe('sumAll function', () => {
it('어레이 내 모든 엘리먼트 더하기', () => {
const result = fn.sumAll([10, 9, 8])
expect(result).toEqual(27)
})
it('어레이에 문자열이 있을 경우', () => {
const arr = [2, 'D', 'C']
const result = fn.sumAll(arr)
expect(arr).toEqual([2, 'D', 'C'])
expect(result).toEqual('2DC')
})
it('빈 어레이가 전달될 경우', () => {
const result = fn.sumAll([])
expect(result).toEqual(0)
})
})
4. 테스트 케이스에 맞춰, 함수를 작성하기
이제 테스트 케이스가 준비되었으므로, 테스트 케이스를 모두 만족할 수 있는 함수를 작성하면 된다.
그 전에 몇가지 설정을 해줄 것이 있다.
기본적으로, 테스트 케이스는 module 객체를 다른 js 파일로부터 넘겨받으므로,,,
함수를 작성하는 js 파일에서는
module.exports를 통해 함수(또는 함수를 담은 객체)를 테스트 케이스로 넘겨주어야 한다.
이는 아래와 같이 작성할 수 있다.
// 파일명은 fn.js 로 해야한다. 테스트케이스가 require('fn.js')로 module을 받기 때문이다.
const allFn = {}
// allFn.작성할 함수 = () => { ... }
module.exports = allFn
이후 함수를 작성할 때, allFn에 속한 메서드의 형태로 함수를 작성해주면 된다.
const allFn = {}
allFn.sumAll = (arr) => {
return arr.reduce((acc, e) => {
acc = acc + e
return acc
})
}
module.exports = allFn
배열 내 모든 엘리먼트를 더해주는 역할을 하는 함수를 작성해야 하므로
reduce 메서드를 통해 문제를 해결해보고자 했다.
이제 테스트 케이스를 실행시켜보자.
5. 테스트 케이스 실행하기
테스트 케이스를 실행하기 위해서는 터미널에서 테스트 케이스 파일이 있는 경로에 명령어로
npx jest 파일명.test.js 를 타이핑해주고 엔터를 치면 된다.
(npx는 패키지를 실행하는 명령어이고,
jest는 테스트 케이스를 실행시켜주기 위해 앞에 적어줘야 하는 명령어이다.)
일단 위의 테스트 케이스를 실행해보자.
테스트케이스에서 2가지 테스트를 통과했지만,
빈 어레이가 전달될 경우, 숫자 0을 리턴한다는 테스트 케이스는 통과하지 못했다.
그럼 이제 이 반례를 통과할 수 있도록 함수를 수정해주면 된다.
// fn.js
const allFn = {}
allFn.sumAll = (arr) => {
if (arr.length === 0) return 0
return arr.reduce((acc, e) => {
acc = acc + e
return acc
})
}
module.exports = allFn
함수를 수정한 후 테스트 케이스를 다시 돌려보았다.
이제 모든 테스트 케이스를 통과하는 함수가 작성되었다.
'Javascript' 카테고리의 다른 글
이벤트 연습 / 마우스 좌표 찍기, input + keyup 이벤트 (3) | 2022.10.25 |
---|---|
이벤트 드리븐 프로그래밍 / 자주 쓰는 이벤트 타입 (0) | 2022.10.25 |
의도적으로 콜백지옥 만들기 (0) | 2022.10.19 |
this에 관하여 (2) | 2022.10.15 |
reduce 심화 학습 (오브젝트에 reduce 활용하기) (0) | 2022.10.13 |