
이 문서는 Jest를 활용하여 TypeScript 코드를 테스트하는 방법과 테스트 환경 설정에 관한 내용을 다룹니다.
testing-library/dom을 적용하여 DOM 조작을 테스트하는 환경을 설정하고, Jest 성능 개선 방법을 다룹니다.
Rune 의 컴포넌트 클래스는 render 메서드를 기본적으로 가지고 있습니다.
render 메서드는 최종적으로 HTMLElement를 리턴하기 때문에 이를 DOMTree 로 구성하고 테스트 할 수 있는 라이브러리인 @testing-library/dom을 적용 했습니다.
testing-library는 React 및 DOM 요소의 사용자 상호작용을 기반으로 테스트를 작성할 수 있는 라이브러리입니다.
이를 통해 UI 테스트를 사용자 관점으로 진행할 수 있습니다.
• ts-jest는 Jest와 TypeScript를 통합하기 위한 도구로, TypeScript 파일을 Jest가 테스트할 수 있도록 변환합니다.
npm install --save-dev jest ts-jest @types/jest
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
기본설정법은 위와 같습니다.
다만, js는 기본 babel-jest 를 사용하고 ts 파일에 대해서만 ts-jest 를 사용하고 싶었기에 아래와 같이 설정했습니다.
module.exports
preset: 'ts-jest',
testEnvironment: 'node',
moduleFileExtensions: ['js', 'mjs', 'cjs', 'json', 'ts'],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
'^.+\\.(js|mjs)$': 'babel-jest',
},
...
}
testing-library/dom 을 사용하기 위해 3가지 모듈을 설치 했습니다.
//package.json
"jest-environment-jsdom": "^29.7.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
jest-environment-jsdom : jsdom 기반으로 가상의 DOM 환경을 구성해주는 Jest 환경 설정@testing-library/jest-dom : Jest 전용 확장 Matcher 제공@testing-library/dom : jsdom(또는 브라우저) 환경에서 HTML 요소에 접근하고 조작하는 라이브러리screen, getByText, fireEvent 등 DOM을 조작하고 추출할 수 있는 함수들을 가지고 있습니다.// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom', // jsdom 환경 설정
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], // 전역 설정 파일 (선택)
moduleFileExtensions: ['ts', 'tsx', 'js'],
testMatch: ['**/__tests__/**/*.test.(ts|tsx|js)'],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
};
문제상황 : 기존 단위 테스트들은 Node 환경에서 테스트 되어 왔습니다.
하지만 jsdom 환경으로 jest를 실행시켜야만 dom에 대한 테스트가 가능해 집니다.
이를 어떻게 해결해야 할까요?
jest config 중 project라는 설정이 있습니다.
module.exports = {
maxWorkers: 1,
projects: [
{
displayName: 'node',
testEnvironment: 'node',
testMatch: [
'<rootDir>/modules/**/*.spec.(js|cjs|mjs|ts)',
'<rootDir>/services/**/*.spec.(js|cjs|mjs|ts)',
],
testPathIgnorePatterns: ['\\.dom\\.spec\\.ts$'], //dom 테스트 제외
moduleFileExtensions: ['js', 'mjs', 'cjs', 'json', 'ts'],
...
},
{
displayName: 'jsdom',
testEnvironment: 'jsdom',
testMatch: ['<rootDir>/services/**/*.dom.spec.(ts|js)'],
moduleFileExtensions: ['js', 'mjs', 'cjs', 'json', 'ts'], ...
},
],
};
**.dom.* 형태로 규정지었습니다.문제상황 : 두근 거리는 마음으로 테스트를 돌리려는 찰나에 글로벌 i18n 인스턴스가 undefined 가 되어 출력되는 이슈가 발생 했습니다!
실제로 i18n 인스턴스를 글로벌 객체에 넣어서 쓰고 있는 구조이므로, 주입이 필요한 상황입니다.
이를 해결하기 위해 setup 파일을 구성하고 글로벌 객체에 필요한 값을 주입해 주는 코드를 작성하고, 이를 Jest가 공통적으로 실행하도록 설정하여 해결했습니다.
// setup.ts
import i18next from 'i18next';
type I18nInstance = {
(lng?: string): Promise<(key: string, options?: any) => string>;
lang: string;
};
let isInit = false;
// I18N INIT 셋업
(async function initTranslator() {
if (isInit) return;
const lang = process.env.LANG || 'kr';
const t = await i18next.init({
lng: lang,
fallbackLng: 'kr',
resources: {},
});
isInit = true;
global.T = t;
// jest.config.cjs
module.exports = {
setupFilesAfterEnv: ['<rootDir>/jest/setup.ts'],
};

와 더불어 jest 성능 개선 방법을 다음 시간에 알아보겠습니다.
와 잘봤습니다!!
힙메모리 이슈 너무 궁금하네요🧐