프론트엔드 테스팅 Jest 톺아보기! 🧪
프론트엔드 개발에서 테스팅은 우리가 만든 코드가 의도한 대로 동작하는지 검증하는 중요한 과정이에요.
코드의 품질을 높이고, 버그를 사전에 예방하며, 유지보수를 용이하게 만드는 데 필수적입니다.
하지만 많은 개발자가 테스트를 귀찮아하고, 필요성을 잘 느끼지 못하는 경우가 많죠. 🤔 (제가 그랬네요,,,)
의외로 막상 시작해보면 꽤 재밌는 부분들이 많습니다!
자, 이제 Jest부터 시작해봅시다! 🚀
🎯 왜 테스트가 필요할까?
프론트엔드에서 테스트를 하지 않아도 당장 동작하는 UI를 만들 수 있어요. 하지만 다음과 같은 문제들이 발생할 수 있죠.
- 😱 예기치 않은 버그 발생: 작은 변경이 전체 기능을 망가뜨릴 수도 있음
- 🛠 리팩토링이 어려움: 코드 수정할 때마다 정상 동작하는지 확인해야 함
- 🤯 수동 테스트의 한계: 모든 기능을 직접 클릭해서 테스트하는 건 비효율적
💡 테스트 자동화를 하면?
- ✅ 코드 변경에도 안정적인 동작 보장
- ✅ 빠르게 피드백을 받아 버그 방지
- ✅ 반복적인 수동 테스트를 줄여 개발 생산성 증가
테스트의 진정한 필요성은 기능이 추가됐을 때 라고 합니다. 어디서 오류가 나는지 어디에 허점이 있는지 아주 상세하게 알 수 있어요.
🧪 Jest란?
Jest는 Facebook에서 만든 JavaScript 테스트 프레임워크로, 프론트엔드 단위 테스트를 쉽게 작성할 수 있도록 도와줘요.
✅ Jest의 특징
- ✔️ 빠른 실행 속도 – 테스트를 병렬로 실행해 속도가 빠름
- ✔️ 간단한 설정 – 별도 설정 없이 바로 사용 가능
- ✔️ Mocking 지원 – API 호출이나 함수 호출을 가짜(mock)로 대체 가능
- ✔️ 스냅샷 테스트 지원 – UI 변경을 감지하는 기능
⚡ Jest 설치 및 기본 설정
📌 Jest 설치하기
먼저, Jest를 설치해볼게요.
yarn add --dev jest
📌 TypeScript를 사용한다면?
yarn add --dev @types/jest ts-jest
📌 React 프로젝트에서 추가적으로 필요한 패키지
npm install --save-dev babel-jest @babel/preset-env @babel/preset-react
설치가 완료되면 package.json에 아래와 같이 Jest 설정을 추가해주세요.
"scripts": {
"test": "jest"
}
이제 npm test 또는 yarn test 명령어를 실행하면 Jest가 실행됩니다. 🎉
(위는 간소화된 버전으로 다양한 기능들을 사용하고 싶다면 더 많은 패키지들이 피룡합니다!)
🎯 Jest의 동작 원리
Jest는 테스트 러너(Test Runner) 역할을 합니다. 즉, 작성된 테스트 코드를 실행하고, 테스트 결과를 자동으로 비교하여 성공/실패를 판별하는 도구예요.
✅ Jest가 테스트를 실행하는 과정
- 1️⃣ npm test 실행 → Jest가 프로젝트에서 *.test.js 또는 *.spec.js 파일을 찾음
- 2️⃣ 각 테스트 파일을 독립적인 환경에서 실행
- 3️⃣ expect()로 작성된 검증(Assertion) 코드를 실행
- 4️⃣ 예상값과 실제값을 비교
- 5️⃣ 테스트 결과를 터미널에 출력
💡 Jest는 테스트를 실행할 때
각 테스트 파일을 독립적인 환경에서 실행하기 때문에, 하나의 테스트가 다른 테스트에 영향을 미치지 않아요.
🤓 Jest 작성 규칙
1️⃣ describe
- ✔️ 용도: 관련된 테스트를 그룹화합니다.
- ✔️ 형식: describe('설명', () => { ... });
📌 코드 예시
describe('수학 함수 테스트', () => {
// 관련 테스트를 여기서 작성
});
2️⃣ test 또는 it
- ✔️ 용도: 개별 테스트 케이스를 정의합니다.
- ✔️ 형식: test('설명', () => { ... }); 또는 it('설명', () => { ... });
test('1 + 2는 3이어야 한다', () => {
expect(sum(1, 2)).toBe(3);
});
3️⃣ expect
- ✔️ 용도: 예상 결과를 정의합니다. 테스트가 성공하기 위해서는 이 예상 결과가 충족되어야 합니다.
- ✔️ 형식: expect(값).toBe(기대값);
expect(sum(1, 2)).toBe(3);
🔍 Jest의 비교 메서드 (Matcher)
Jest는 다양한 비교 메서드(Assertion Matcher)를 제공해요.
✅ 기본적인 비교 메서드
expect(value).toBe(expected); // === 비교
expect(value).not.toBe(expected); // !== 비교
expect(value).toEqual(expected); // 객체/배열 비교
expect(value).toBeTruthy(); // true 값인지 확인
expect(value).toBeFalsy(); // false 값인지 확인
✅ 배열과 객체 비교
toBe()는 객체의 참조(메모리 주소)를 비교하지만, toEqual()은 객체의 속성 값을 비교해요.
test('객체 비교 테스트', () => {
expect({ name: 'Alice' }).toEqual({ name: 'Alice' }); // ✅ 통과
expect({ name: 'Alice' }).toBe({ name: 'Alice' }); // ❌ 실패
});
🏗 Jest로 단위 테스트 작성하기
1️⃣ 첫 번째 테스트: 숫자 연산 검증
테스트 파일을 생성해볼까요? sum.js 파일을 만들고, 아래처럼 간단한 함수를 작성해요.
// sum.js
export function sum(a, b) {
return a + b;
}
이제 sum.test.js에서 Jest 테스트를 작성해봅시다.
// sum.test.js
import { sum } from './sum';
test('1 + 2는 3이어야 한다', () => {
expect(sum(1, 2)).toBe(3);
});
✅ 코드 설명
- ✔️ test(description, callback) – 테스트 케이스 정의
- ✔️ expect(value).toBe(expected) – 값이 예상대로 나오는지 검증
이제 터미널에서 실행해보세요!
npm test
✅ 테스트 통과! 🎉
터미널 출력 예시:
PASS ./sum.test.js
✓ 1 + 2는 3이어야 한다 (5ms)
🏗 Jest 테스트 오류 확인 및 디버깅
테스트를 실행하면 Jest는 다음과 같은 정보를 터미널에 출력합니다.
✅ 성공한 테스트 예시
PASS ./sum.test.js
✓ 1 + 2는 3이어야 한다 (5ms)
- ✔️ PASS는 테스트가 정상적으로 통과했다는 의미
- ✔️ ✓ 표시가 나오면 테스트가 성공
🚨 4. 테스트 오류 확인 및 디버깅
테스트 코드가 실패하면, Jest는 실제 결과와 기대한 결과의 차이를 알려줍니다.
📌 예를 들어, 아래와 같이 sum(1, 2)가 잘못된 결과(4)를 반환한다고 가정해볼게요.
test('1 + 2는 3이어야 한다', () => {
expect(sum(1, 2)).toBe(4); // ❌ 오류 발생
});
📌 터미널에서 출력되는 에러 메시지
FAIL ./sum.test.js
✕ 1 + 2는 3이어야 한다 (10ms)
● 1 + 2는 3이어야 한다
expect(received).toBe(expected) // Object.is equality
Expected: 4
Received: 3
2 | test('1 + 2는 3이어야 한다', () => {
3 | expect(sum(1, 2)).toBe(4);
| ^
- ✔️ FAIL이 나오면 테스트 실패
- ✔️ Expected: 3, Received: 4 → 기대한 값과 실제 값이 다름
✅ 오류 해결 방법
- Expected: 4, Received: 3 👉 예상한 값(4)과 실제 값(3)이 다름
- 오류가 발생한 코드의 줄 번호(2 | test('1 + 2는 3이어야 한다') 표시됨
- sum(1, 2)를 다시 확인해 3이 나오도록 수정
🏗 Jest로 비동기 코드 테스트하기
프론트엔드에서는 API 요청을 다루는 경우가 많아요. Jest는 비동기 코드도 테스트할 수 있습니다.
// fetchUser.js
export async function fetchUser(id) {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
return response.json();
}
이제 fetchUser.test.js에서 Jest 테스트를 작성해봅시다.
// fetchUser.test.js
import { fetchUser } from './fetchUser';
test('API에서 사용자 정보를 가져와야 한다', async () => {
const user = await fetchUser(1);
expect(user).toHaveProperty('id', 1);
});
💡 비동기 테스트에서는 async/await을 사용해서 데이터를 기다린 후 검증하면 돼요.
🏗 Jest Mocking: API 호출 없이 테스트하기
실제 API를 호출하지 않고 가짜(mock) 데이터를 사용해서 테스트할 수도 있어요.
// fetchUser.js
export async function fetchUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
return response.json();
}
테스트 코드에서 jest.fn()을 사용해 API 호출을 모킹(mocking)할 수 있어요.
// fetchUser.test.js
import { fetchUser } from './fetchUser';
jest.mock('./fetchUser', () => ({
fetchUser: jest.fn(),
}));
test('Mocked API 호출 테스트', async () => {
fetchUser.mockResolvedValue({ id: 1, name: 'John Doe' });
const user = await fetchUser(1);
expect(user).toEqual({ id: 1, name: 'John Doe' });
});
💡 실제 API 요청을 하지 않으므로 테스트 속도가 빨라지고 안정성이 높아집니다. 🚀
📸 Jest 스냅샷 테스트
스냅샷 테스트는 UI가 예상대로 렌더링되는지 확인하는 테스트 방법이에요.
Jest는 컴포넌트의 출력을 파일로 저장한 후, 이후 실행 시 기존 스냅샷과 비교하여 변경 여부를 확인해요.
✅ 스냅샷 테스트 예제
import renderer from 'react-test-renderer';
import Button from './Button';
test('버튼 스냅샷 테스트', () => {
const tree = renderer.create(<Button label="Click me" />).toJSON();
expect(tree).toMatchSnapshot();
});
📌 첫 실행 시, Jest는 __snapshots__ 폴더에 스냅샷 파일을 생성해요.
📌 이후 변경된 UI가 기존 스냅샷과 다르면 테스트가 실패하고, 수정 여부를 묻습니다.
✅ UI 변경 후 스냅샷 업데이트
npm test -- -u
🎯 마무리
✅ Jest는 단위 테스트를 쉽게 작성할 수 있도록 도와주는 강력한 도구
✅ 다양한 비교 메서드(Assertion Matcher) 제공
✅ 비동기 코드, API 호출, Mocking 등 다양한 방식으로 테스트 가능
✅ 터미널에서 테스트 결과 확인 및 오류 디버깅 가능
✅ 스냅샷 테스트로 UI 변경 감지 가능
🌷 전설의 개발자가 되어봅시당! 🌷
'Front-end > Test' 카테고리의 다른 글
🎭 Jest: JavaScript 테스팅의 강력한 도구 (0) | 2025.03.12 |
---|---|
[TDD] 프론트엔드 테스팅 3편: React Testing Library(RTL) Mocking Spying 🧪 (1) | 2025.02.04 |
[TDD] 프론트엔드 테스팅 2편: React Testing Library(RTL) 컴포넌트 테스트 🧪 (0) | 2025.02.03 |