Jest는 메타(Meta)에서 개발한 JavaScript의 테스트 프레임워크 입니다.
Babel, TypeScript, Node.js, React, Angular, Vue.js, Svelte 등 에서 사용되며 단위 테스트와 통합 테스트에서 사용됩니다.
$npm i --save-dev jest
를 통해 설치합니다.
// pacakge.json
...
"scripts" : {
"test" : "jest"
}
...
이렇게 package.json에 작성한다면, npm test
를 통해 간단하게 jest 실행이 가능합니다.
test 파일은 파일이름.test.js
로 만듭니다.
예를 들면
example.ts
라는 파일에 대한 테스트 파일을 만들 때,
example.test.js
로 생성합니다.
이 때 아래와 같이 개별 테스트를 작성합니다.
Jest에서 테스트 케이스는 test
와 it
함수를 통해 정의가능합니다.
test('Add Test', () => {
expect(1 + 2).toBe(3);
});
it('should calculate the sum of two numbers', () => {
expect(1 + 2).toBe(3);
});
이는 취향 차이로 개발자에 따라 원하는 것을 사용하면 됩니다.
test('Componenet Snapshot', () => {
const tree = renderer.create(<MyComponent />).toJSON();
expect(tree).toMatchSnapshot();
});
// 1. MyComponent를 렌더링
// 2. toJSON()을 통해 메서드 호출하여 JSON으로 변환
// 3. expect(tree).toMatchSnapshot()을 통해 이전에 저장한 스냅샷과 현재 렌더링 결과 비교
UI 컴포넌트의 랜더링 결과를 스냅샷으로 저장하여 테스트에서 비교합니다.
이를 통해 UI 변경을 감지할 수 있습니다.
const fetchData = jest.fn().mockReturnValueOnce(10);
test('Mock Function Test', () => {
expect(fetchData()).toBe(10);
});
// 1. jest.fn()을 통한 모의 함수 생성
// 2. mockReturnValueOnce()로 메서드 호출 될 때 마다 반환 값 설정
// 3. fetchData()를 통해 설정된 반환 값이 올바른지 확인
모의 함수를 생성하여 다른 함수의 호출을 추적하여, 반환 값을 지정합니다.
이는 의존성을 격리한 상태에서 테스트할 수 있습니다.
const fetchData = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('Data');
}, 1000);
});
};
test('Async Test', async () => {
const data = await fetchData();
expect(data).toBe('Data');
});
// 1. fetchData()를 통한 비동기 함수 정의
// 2. async를 통한 비동기 테스트
// 3. await을 통해 기다린 후 expect를 통한 예상 값과의 비교
Jest를 통한 비동기 테스트는 async/await을 사용하거나,
done 콜백을 통해 비동기 테스트를 작성할 수 있습니다.
const fetchData = (callback) => {
setTimeout(() => {
callback('Data');
}, 1000);
};
test('Async Test', (done) => {
fetchData((data) => {
expect(data).toBe('Data');
done(); // done()을 통해 테스트가 완료됨을 명시
});
});
describe는 Jest에서 테스트 케이스를 그룹화하는 테스트 스위트(Test Suite)를 정의합니다.
describe를 통해 테스트를 그룹화하는 것은 물론 공통 설정을 정리할 수 있고,
이를 계층 구조로 만들어 복잡한 테스트를 처리할 수 있습니다.
describe('Calculator Functions', () => {
test('add Test', () => {
expect(add(1, 2)).toBe(3);
});
test('subtract Test', () => {
expect(subtract(5, 2)).toBe(3);
});
});
관련 테스트 케이스를 하나의 그룹으로 묶어 구조 명확성과 가독성을 높입니다.
describe('Database Test', () => {
beforeAll(() => {
// 데이터베이스 초기화
});
afterAll(() => {
// 데이터베이스 정리
});
test('Data Add Test', () => {
// 테스트 코드
});
});
beforeAll, beforeEach, afterAll, afterEach 함수를 사용하여 테스트 실행 전후에 필요한 설정과 정리를 할 수 있습니다.
describe('Component', () => {
describe('...', () => {
test('...', () => {
// 테스트 코드
});
});
describe('...', () => {
test('...', () => {
// 테스트 코드
});
});
});
계층 구조를 통해 복잡한 테스트 생성이 가능합니다.
커버리지(Coverage)란 테스트에서 얼마나 많은 코드를 실행했는지 측정하는 지표로
Jest 커버리지 보고서는 다음과 같이 생성 가능합니다.
jest --coverage
이는 HTML 형식으로 Jest 커버리지 보고서를 coverage 폴더에 저장합니다.
커버리지 설정은 jest.config.js
를 통해 가능합니다.
// jest.config.ts
module.exports = {
collectCoverage: true,
coverageThreshold: {
global: {
branches: 90,
functions: 90,
lines: 90,
statements: 90,
},
},
};
collectCoverage
: 이것이 true
라면 커버리지 정보를 수집 후 출력합니다.coverageThreshold
: 각 항목에 대한 수치를 정의하고 해당 코드에 경우 90% 이상이어야만 테스트를 통과합니다Jest는 JavaScript에 대표적인 테스트 프레임워크로,
간편한 설정, Mock 함수 생성 가능, 병렬 실행, 활발한 커뮤니티 등의 장점이 있습니다.
그렇다면 비슷한 것들은 무엇이 있을까요?
Jest에 비해 다양한 라이브러리와 사용할 수 있어 유연하며,
자유로운 설정을 통해 프로젝트 요구에 맞게 사용자 정의가 가능합니다.
또한 NodeJS에 적합합니다.
하지만, 기본 설정이 없어 초기 설정이 필요하고,
스냅샷 테스트를 제공하지 않습니다.
또한 React에는 Jest가 유리합니다.
Jasmine은 BDD 스타일로 가장 자연어에 가깝고,
프론트엔드 테스트에서 가장 많이 선호됩니다.
다만, 비동기 테스트작성이 다소 복잡하고,
DOM(Document Object Model)을 제공하지 않습니다.
Jest는 가장 많이 사용되는 테스트 프레임워크 중 하나로, 이는 많은 자료와 커뮤니티 형성을 통해 실제로 활용하기 매우 편리합니다.
웹을 개발하는 것에 비해 테스트 하는 것은 익숙치 않아 이것을 제대로 이용하려면 개념 공부를 통해 활용 방안과 장단점을 아는 것이 중요합니다.
테스트를 통해 개발의 오류를 줄이고,
나에게 맞는 테스트 프레임워크를 사용하자⭐