반응형
Jest란
- Jest는 JavaScript 테스팅 프레임워크로, 주로 Node.js 애플리케이션을 테스트하는 데 사용된다.
- Facebook에서 개발했으며, 여러 가지 강력한 기능과 도구들을 제공하여 테스트 작성과 실행을 쉽게 만든다
장점
- 간편한 설정: Jest는 설정이 거의 필요 없도록 설계되었고 기본 설정으로도 대부분의 프로젝트에서 바로 사용할 수 있다.
- 스냅샷 테스트: Jest는 컴포넌트의 출력이나 함수의 반환값을 스냅샷으로 저장하고, 이후 테스트 실행 시 이 스냅샷과 비교하여 변경 사항을 감지한다
- 모의 함수와 모듈: Jest는 테스트 중 특정 함수나 모듈을 모의(mock)하여 테스트 환경을 제어할 수 있는 기능을 제공한다
- 비동기 코드 테스트: 콜백, 프로미스, async/await 등을 포함한 비동기 코드를 쉽게 테스트할 수 있는 방법을 제공한다
- 병렬 테스트 실행: 여러 테스트를 병렬로 실행하여 테스트 속도를 높인다
- 코드 커버리지: Jest는 테스트 커버리지 보고서를 생성하여 코드베이스에서 테스트되지 않은 부분을 쉽게 확인할 수 있다
- 타임 트래블 기능: 테스트 중 타이머를 제어하고, 시간을 빠르게 감거나 느리게 할 수 있는 기능을 제공한다
단점
- 학습 곡선: Jest의 다양한 기능과 설정 옵션들을 모두 이해하고 활용하는 데 시간이 걸릴 수 있다. 특히 처음 사용하는 경우, 설정과 모의(Mock) 기능 등을 익히는 데 어려움을 겪을 수 있다
- 퍼포먼스: 대규모 프로젝트에서 많은 테스트 케이스를 실행할 때 성능 문제가 발생할 수 있다. Jest는 기본적으로 병렬 테스트 실행을 지원하지만, 여전히 테스트 시간이 오래 걸릴 수 있다.
- 모듈 모킹의 한계: Jest의 모듈 모킹 기능이 강력하지만, 특정 시나리오에서는 예상치 못한 동작을 할 수 있습니다. 특히 복잡한 모듈 의존성을 가진 프로젝트에서는 모킹이 어려울 수 있다.
- 생태계 종속성: Jest는 주로 React와 관련된 프로젝트에서 많이 사용되지만, 다른 프레임워크나 라이브러리와의 호환성 문제도 있을 수 있다. 예를 들어, Angular 프로젝트에서는 다른 테스팅 프레임워크(예: Karma, Jasmine)가 더 적합할 수 있다.
- 디버깅의 어려움: 테스트 실패 시 원인을 파악하고 디버깅하는 과정이 복잡할 수 있다. 특히 비동기 코드나 복잡한 상태 관리를 테스트할 때 문제가 발생할 수 있다.
- 커뮤니티 지원: Jest는 많은 사용자와 활발한 커뮤니티를 가지고 있지만, 특정 문제에 대한 해결책을 찾는 데 어려움을 겪을 수 있다.
활용 실습
초기 환경 구성
install
npm i -D jest
package.json
{
"name": "project name",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest --watchAll"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.19.2",
"jest": "^29.7.0"
}
}
run
npm run test
명명 규칙
- 파일 확장자
- *.test.js/ts, *.spec.js/ts와 같은 확장자를 사용한다
- 테스트 파일 위치
- 테스트 파일은 소스 파일과 같은 디렉토리에 저장한다
- 같은 모듈의 계층에 생성
- 보통의 클래스와 구분하기 위해서 “Test”라는 접미사를 붙이는 것을 당연한 규칙으로 자리 잡고 있다
- describe("", () => { const somethingClassTest = new SomethingClass(); // ... test code });
단언 메서드(Assertion Method)
- Test Case의 실행 결과를 판별해주는 메서드
주요 메서드(JUnit과 비교)
- toBe ↔️ assertEquals : 원시 값이 동일한지 확인
- toEqual ↔️ assertEquals : 객체나 배열의 값이 동일한지 확인
- 객체 비교 시 assertEquals가 아니라 equals 사용
- toBeNull ↔️ assertNull : null인지 확인
- toBeUndefined ↔️ assertNull : undefined인지 확인
- toBeDefined ↔️ assertNotNull : undefined가 아닌지 확인
- toBeTruthy ↔️ assertTrue : true로 평가될 수 있는지 확인
- toBeFalsy ↔️ assertFalse : false로 평가될 수 있는지 확인
- toContain ↔️ (assertTrue, contains) : 배열이나 문자열이 특정 요소를 포함하는지 확인
- toThrow ↔️ assertThrows : 함수가 예외를 던지는지 확인
- throw ↔️ fail : 테스트를 실패 시키고자 할 때 사용
- 그 외 Jest Assertion Method
- toBeGreaterThan
- toBeLessThan
- toHaveLength
- toMatch
- toMatchObject
- …
실습
toBe
describe("기본 문법 테스트", () => {
test("기본 테스트", () => {
const actual = 1;
const expected = 2;
expect(actual).toBe(expected); // failed
});
});
FAIL test/syntax.test.js
기본 문법 테스트
✕ 기본 테스트 (8 ms)
● 기본 문법 테스트 › 기본 테스트
expect(received).toBe(expected) // Object.is equality
Expected: 2
Received: 1
3 | const actual = 1;
4 | const expected = 2;
> 5 | expect(actual).toBe(expected);
| ^
6 | });
7 | });
8 |
at Object.toBe (test/syntax.test.js:5:20)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.524 s, estimated 1 s
-------------------------------------------------------------------------
describe("기본 문법 테스트", () => {
test("기본 테스트", () => {
const actual = 2;
const expected = 2;
expect(actual).toBe(expected);
});
});
PASS test/syntax.test.js
기본 문법 테스트
✓ 기본 테스트 (6 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.469 s, estimated 1 s
Ran all test suites.
Watch Usage: Press w to show more.
toThrow
class Syntax {
upperCase(str) {
if (!str) throw new Error("No string provided");
return str.toUpperCase();
}
}
test("throw 테스트", () => {
const syntax = new Syntax();
expect(() => syntax.upperCase()).toThrow("No string provided");
expect(() => syntax.upperCase("hello")).not.toThrow();
expect(syntax.upperCase("hello")).toBe("HELLO");
});
PASS test/syntax.test.js
기본 문법 테스트
✓ 기본 테스트 (5 ms)
✓ throw 테스트 (7 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 0.371 s, estimated 1 s
Ran all test suites.
Watch Usage: Press w to show more.
throw
describe("기본 문법 테스트", () => {
test("throw 테스트", () => {
try {
const syntax = new Syntax();
syntax.upperCase("");
} catch (error) {
expect(error.message).toBe("Error");
}
});
});
PASS test/syntax.test.js
기본 문법 테스트
✓ 기본 테스트 (3 ms)
✓ toThrow 테스트 (5 ms)
✓ throw 테스트
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 0.501 s, estimated 1 s
Ran all test suites.
Watch Usage: Press w to show more.
Test LifeCycle(JUnit과 비교)
- Class Level Setup beforeAll ↔️ @BeforeAll
- 한 클래스의 모든 테스트가 메서드가 실행되기 전에 특정 작업을 수행해야 하는 경우
- 모든 테스트가 실행되기 전에 한 번 실행됨
- Setup beforeEach ↔️ @BeforeEach
- 테스트를 실행하는데 필요한 준비 작업을 할 때 사용됨
- 임시 파일을 생성한다거나 테스트 메서드에서 사용할 객체를 생성할 수 있다
- 각 테스트가 실행되기 전에 실행됨
- Test Execution it(test) ↔️ @Test
- 개발자가 의도했던 테스트 결과가 나오는지 확인하는 단계
- Clean-up afterEach ↔️ @AfterEach
- 테스트 종료 후, 정리할 것이 있을 때 사용
- 사용한 리소스를 반환하거나 임시로 사용한 파일을 삭제하는 기능을 여기서 진행
- 각 테스트가 실행된 후에 실행됨
- Class Level Clean-up afterAll ↔️ @AfterAll
- 모든 테스트가 끝나는 시점
- 테스트 환경에 부가적으로 필요했던 인스턴스의 리소스 반환이나 종료 등을 여기서 진행
- 모든 테스트가 실행된 후에 한 번 실행됨
class Lifecycle {
constructor() {
this.data = [];
}
add(item) {
this.data.push(item);
}
remove(item) {
this.data = this.data.filter((i) => i !== item);
}
get() {
return this.data;
}
clear() {
this.data = [];
}
}
describe("LifeCycle Test", () => {
let lifecycle;
// Class Level Setup
beforeAll(() => {
console.log("beforeAll");
});
// Setup
beforeEach(() => {
console.log("beforeEach");
lifecycle = new Lifecycle();
});
// Cleanup
afterEach(() => {
console.log("afterEach");
});
// Class Level Cleanup
afterAll(() => {
console.log("afterAll");
});
// Test Execution
test("add test", () => {
lifecycle.add(1);
lifecycle.add(2);
expect(lifecycle.get()).toEqual([1, 2]);
});
});
// beforeAll → beforeEach → (Test Execution) → afterEach → afterAll 순으로 실행
-----------------------------------------------------------------------------
PASS test/syntax.test.js
PASS test/lifecycle.test.js
● Console
console.log
beforeAll
at Object.log (test/lifecycle.test.js:28:13)
console.log
beforeEach
at Object.log (test/lifecycle.test.js:33:13)
console.log
afterEach
at Object.log (test/lifecycle.test.js:39:13)
console.log
afterAll
at Object.log (test/lifecycle.test.js:44:13)
Test Suites: 2 passed, 2 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 0.518 s, estimated 1 s
Ran all test suites.
Watch Usage: Press w to show more.반응형
'TDD' 카테고리의 다른 글
| Jest 많이 썼던 내용들 정리 (1) (5) | 2024.10.24 |
|---|---|
| 간단한 게시판 만들면서 TDD 맛보기 (POST 요청) (1) | 2024.09.01 |
| Jest; JUnit 어노테이션을 참고한 (0) | 2024.08.31 |
| 예제; 암호 검사기 (0) | 2024.08.31 |
| 테스트의 개념과 중요성 (0) | 2024.08.31 |