자바스크립트의 테스팅 프레임워크 Jest를 설치하고 사용하는 방법을 정리한다.
Jest is a delightful JavaScript Testing Framework with a focus on simplicity.
It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!-- Jest 공식 홈페이지 메인
Jest는 자바스크립트 소스코드를 테스트할 때 사용하는 프레임워크이다.
자바스크립트의 테스팅에는 주로 Jest와 Mocha 둘 중 하나가 사용된다고 하는데, 둘은 다음과 같은 장단점을 가진다.
Jest
장점
단점
Mocha
장점
단점
아래와 같이 jest를 설치한다.
(npm)
npm install --save-dev jest
(yarn)
yarn add --dev jest
설치가 완료되었으면, package.json에 아래 내용을 추가해주자.
// package.json
{
// ...
"scripts": {
"test": "jest"
}
// ...
}
이렇게 하면, npm test
혹은 yarn test
라는 명령어 하나만으로 사전에 정의된 테스트들을 한번에 테스트할 수 있다.
// test.js
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
설치 및 환경 세팅이 잘 되었는지 확인하기 위해, 위 파일을 test.js
라는 이름으로 프로젝트 디렉토리에 추가한 뒤, npm test
혹은 yarn test
을 사용해 테스트를 해보자.
무슨 의미인지 직관적으로 알 수 있을 것인데, Jest에서 제공하는 기능들에 대한 더 자세한 설명은 아래 섹션에서 마저 해볼 것이다.
describe('Calculation test', () => {
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
test('adds -2 + 2 to equal 0', () => {
expect(sum(-2, 2)).toBe(0);
});
});
Jest에서 테스트는 test(테스트 이름
, 테스트할 함수
)의 형태로 사용한다.
Jest에서는 기본값으로 test.js
로 끝나거나, __test__
디렉토리 안에 있는 파일 이름들 (e.g. reservation.test.js
, ./__test__/test_a.js
) 안에 있는 모든 test()
함수들에 대해 테스트를 진행한다.
Jest에서 테스트를 묶는 논리적 단위이다.
하나의 describe 안에 여러 개의 test를 두어 하나의 test suite로 만들 수 있다.
describe(테스트 이름
, 테스트할 함수들이 들어 있는 함수
)의 형태로 사용한다.
Jest에서는 일반적으로 expect(검증 대상).matcher(기대값);
와 같은 형태로 테스트를 진행한다.
expect 뒤에 붙는 함수들은 matcher라고 부르며, Jest에서는 여러 종류의 matcher들을 지원한다.
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
앞선 예제에서 나왔던 toBe 함수는 expect()의 인자로 준 값과 toBe()의 인자로 준 값이 같은지 검사한다.
test('checks array equality', () => {
expect([1, 2, 3]).toEqual([1, 2, 3]);
});
toBe와 toEqual은 얼핏 보면 같은 동작을 하는 함수처럼 보이지만,
toBe는 number, boolean과 같은 원시값들이 같은지 검증하는 반면, toEqual은 객체 안의 값이 같은지를 검증한다.
test("number 0 is falsy but string 0 is truthy", () => {
expect(0).toBeFalsy();
expect("0").toBeTruthy();
});
toBeTruthy()와 toBeFalsy()는 자바스크립트의 규칙에 따라, 주어진 값이 false로 평가되는지 true로 평가되는지 판단해 테스트한다.
test("tests array", () => {
const alphabets = ["A", "B", "D"];
expect(alphabets).toHaveLength(3);
expect(alphabets).toContain("A");
expect(alphabets).not.toContain("C");
});
toHaveLength는 주어진 배열의 크기를, toContain은 특정 element가 들어있는지 확인한다.
test("tests username", () => {
const username = 'user1';
expect(username).toMatch(/^[a-z0-9_]+$/i);
});
toMatch는 주어진 값이 정규표현식에 부합하는지 테스트한다.
test("throws error if div by 0", () => {
// Don't
expect(divide(3, 0)).toThrow('You cannot divide something by 0.');
});
주어진 상황에서 예외가 발생하는지 확인하는지 테스트한다.
toThrow() 안의 인자에는 에러 객체의 메시지를 넣는다.
그런데 위 주석처리한 대로 테스트 코드를 짠다면, divide(3, 0)을 처리하며 실제로 0으로 나눌 수 없다는 예외가 발생하여 테스트가 항상 실패하게 될 것이다.
따라서, toThrow()를 사용할 때에는 다른 matcher들과는 달리 아래와 같이 함수로 한 번 감싸서 사용한다.
test("throws error if div by 0", () => {
// Don't
expect(() => { divide(3, 0) }).toThrow('You cannot divide something by 0.');
});
그 외에도 테스트 전/후 처리를 하는 방법이 궁금하다면 아래 블로그를 참고하자.
https://www.daleseo.com/jest-before-after/
Jest를 require를 사용한 commonJs가 아닌, import, export와 같은 문법과 같이 사용하고 싶은 사용자들이 있을 것이다.
하지만 위 설정만으로는 import, export와 같은 문법들을 사용할 수 없고, 사용하려고 하면 아래와 같은 오류 메세지들을 마주하게 된다.
Jest encountered an unexpected token
Cannot use import statement outside module
You appear to be using a native ECMAScript module configuration file, which is only supported when running Babel asynchronously.
Jest와 import, export를 함께 사용하는 방법은 크게 2가지로, 아래와 같이 인터넷에 많이 소개되어 있다.
ES6의 문법들이 사용된 javascript(or typescript) 코드를 ES5의 문법이 사용된 js(ts) 파일로 컴파일하여 사용하는 방법
https://poiemaweb.com/jest-esm
https://velog.io/@dacircle/JEST-import-사용하기
--experimental-vm-modules을 사용한 방법
https://study-ihl.tistory.com/191
그러나 Jest 공식 홈페이지에서는 글을 작성하고 있는 현재(2023.07) 기준으로, ESM(ECMAscript Modules)를 사용하는 데에 주의가 필요하다고 하고 있다.
https://jestjs.io/docs/ecmascript-modules
이는 Jest와 ESM을 함께 사용하는 것이 experimental한 기능이기 때문인데, import, export와 같은 문법을 사용하고자 하는 분들은 버그 혹은 완전치 못한 기능들에 유의하여 Jest를 사용하길 바란다.
Mocha vs Jest Comparison of Testing Tools in 2022
자바스크립트 테스트 프레임워크 비교 (jest, mocha, jasmine)
Mocha vs Jest (JS Testing Framework)