1. Jest란?
- 페이스북에서 만든 Javascript 테스팅 프레임워크
- zero config 실현 : 별도 설정 없이 빠르게 테스트 케이스를 작성할 수 있는 장점이 있다.
2. 구성
새 프로젝트에서 jest와 typescript, es6 모듈 시스템을 사용할 수 있도록 설정한다.
2-1. 설치
yarn add --dev jest ts-jest @types/jest babel-jest @babel/core @babel/preset-env
2-2. 설정
babel.config.json
{
"presets": [["@babel/preset-env", { "targets": { "node": "current" } }]]
}
jest.config.json
{
"collectCoverage": true,
"moduleFileExtensions": ["js", "ts"],
"testMatch": ["**/__tests__/**/*.+(ts|js)", "**/?(*.)+(spec|test).+(ts|js)"],
"transform": {
"^.+\\.(ts)$": "ts-jest"
}
}
package.json
{
...
"scripts": {
"test": "jest"
},
...
}
jest는 yarn test
실행 시 testMatch
와 일치하는 모든 파일을 테스트 코드로 인식하여 테스트를 실행한다. 특정 파일만 테스트 하고 싶다면 yarn test
뒤에 파일명 또는 경로를 입력한다.
3. 시작하기
fn.ts
const fn = {
add: (number1: number, number2: number) => number1 + number2,
}
export default fn
fn.test.ts
import fn from './fn'
// 긍정
test('1 더하기 2는 3이다.', () => {
expect(fn.add(1, 2)).toBe(3)
})
test('0 더하기 1은 1이다.', () => {
expect(fn.add(0, 1)).toBe(1)
})
// 부정
test('3 더하기 3은 5가 아니다.', () => {
expect(fn.add(3, 3)).not.toBe(5)
})
test
: 첫 번째 인수로 테스트 이름, 두 번째 인수로 테스트 함수, 세 번째 인수로timeout
값을 넣는다.
expect
: 검증할 값 /toBe
: 기대하는 값- 매처(Matcher) : 기본형을 비교할 때 사용하며 여러가지 matcher가 있다. ex)
toBe
4. 자주 사용하는 Matcher
4-1. toEqual
기본형에서는 toBe와 유사하게 동작한다.
// 둘 다 테스트 성공
test('0 더하기 1은 3입니다.', () => {
expect(fn.add(0, 1)).toBe(1)
})
test('0 더하기 1은 3입니다.', () => {
expect(fn.add(0, 1)).toEqual(1)
})
하지만 객체, 배열은 재귀적으로 돌며 값을 확인해야 하기 때문에 toBe
로 사용할 수 없으며 toEqual로 비교해야 한다.
fn.ts
const fn = {
add: (number1: number, number2: number) => number1 + number2,
makeUser: (name: string, age: number) => ({ name, age }), // 이름과 나이를 객체로 반환하는 함수 추가
}
export default fn
fn.test.ts
// 테스트 실패
test('이름과 나이를 입력받아 객체로 반환한다.', () => {
expect(fn.makeUser('1000peach', 10)).toBe({
name: '1000peach',
age: 10,
})
})
// 테스트 성공
test('이름과 나이를 입력받아 객체로 반환한다.', () => {
expect(fn.makeUser('1000peach', 10)).toEqual({
name: '1000peach',
age: 10,
})
})
4-1-1. toStrictEqual
보다 엄격하게 비교하려면 toStrictEqual을 사용한다.
위 fn.makeUser
함수에서 gender: undefined
를 반환하게 되면 toEqual
과 toStrictEqual
은 다른 결과를 보인다.
fn.ts
const fn = {
add: (number1: number, number2: number) => number1 + number2,
makeUser: (name: string, age: number) => ({ name, age, gender: undefined }),
}
export default fn
// 테스트 성공
test('이름과 나이를 입력받아 객체로 반환한다.', () => {
expect(fn.makeUser('1000peach', 10)).toEqual({
name: '1000peach',
age: 10,
})
})
// 테스트 실패
test('이름과 나이를 입력받아 객체로 반환한다.', () => {
expect(fn.makeUser('1000peach', 10)).toStrictEqual({
name: '1000peach',
age: 10,
})
})
4-2. toBeNull, toBeUndefined, toBeDefined
- 이름 그대로
null
,undefined
,defined
인 경우 테스트를 통과한다.
// 테스트 성공
test('null은 null이다.', () => {
expect(null).toBeNull()
})
3. toBeTruthy, toBeFalse
boolean 값을 판별한다.
// 테스트 성공
test('비어있지 않은 문자열은 true 다.', () => {
expect('1000peach').toBeTruthy()
})
4-3. toBeGreaterThan, toBeGreaterThanOrEqual, toBeLessThan, toBeLessThanOrEqual
- 숫자의 이상/이하/초과/미만을 판단한다.
- ex) 길이 제한, 업로드된 파일의 크기 확인
// 테스트 실패
test('ID는 10자 이하여야 한다.', () => {
const id = 'HELLO_1000PEACH_WORLD'
expect(id.length).toBeLessThanOrEqual(10)
})
4-3-1. 주의할 점
자바스크립트는 소수점을 완벽히 연산하지 못하므로 자릿수 처리가 필요하다. toBeCloseTo를 사용하여 값이 근사치인 지 테스트해야 한다.
// 테스트 실패. 결과값: 0.3000000..
test('0.1 더하기 0.2는 0.3이다.', () => {
expect(fn.add(0.1, 0.2)).toBe(0.3)
})
// 테스트 성공
test('0.1 더하기 0.2는 0.3이다.', () => {
expect(fn.add(0.1, 0.2)).toBeCloseTo(0.3)
})
4-4. toMatch
해당 문자열을 포함하고 있는 지 판단한다.
// 테스트 성공
test('hello world는 h를 포함한다', () => {
expect('hello world').toMatch(/h/i)
})
4-5. toContain
배열에서 특정 요소가 있는 지 판단한다.
// 테스트 성공
test('유저 리스트에 Mike가 있다.', () => {
const userList = ['Tom', 'Mike', 'Jenny']
const user = 'Mike'
expect(userList).toContain(user)
})
4-6. toThrow
함수에서 예외가 발생했는 지 확인한다. 특정 에러가 발생했는 지 판별하려면 인수로 에러 내용을 전달한다.
fn.ts
const fn = {
add: (number1: number, number2: number) => number1 + number2,
makeUser: (name: string, age: number) => ({ name, age, gender: undefined }),
throwError: () => {
throw new Error('error test')
},
}
export default fn
// 테스트 성공
test('함수 실행 시 에러가 발생한다.', () => {
expect(() => fn.throwError()).toThrow()
})
// 테스트 실패
test('함수 실행 시 error test 에러가 발생한다.', () => {
expect(() => fn.throwError()).toThrow('no error')
})
// 테스트 성공
test('함수 실행 시 error test 에러가 발생한다.', () => {
expect(() => fn.throwError()).toThrow('error test')
})