Jest 동작 과정 밑바닥부터 간단 정리
2025. 5. 11. 16:42ㆍ리액트
728x90
Jest + React Testing Library가 여러분의 ArticleList.test.tsx를 실제로 “돌려” 보기까지, 그리고 개별 test(...) 블록을 실행해 결과를 리포팅하기까지의 상세한 단계를 정리합니다.
1. CLI로 테스트 실행
# 프로젝트 루트에서
npx jest
# 모든 테스트 실행
npx jest src/05/04/ArticleList.test.tsx
# 특정 파일만 실행
- Node 프로세스가 생성되고
- jest.config.js(또는 package.json의 설정)를 읽어서
- 어떤 파일을 테스트로 볼지(testMatch)
- 어떤 “환경”에서 돌릴지(testEnvironment, 보통 "jsdom")
- 어떤 변환(transform)을 거칠지(ts-jest, babel-jest 등)
- 스냅샷 위치(snapshotResolver) 등을 로딩
2. 테스트 파일 수집 & 분할
- 설정에 매칭되는 *.test.tsx 파일을 워커(worker) 프로세스에 분배
- 워커 한 개가 ArticleList.test.tsx만 전담하는 경우가 많음
- 워커는 Node 환경이지만, jest-environment-jsdom을 통해 jsdom 기반의 가상 브라우저 전역객체(window, document)를 갖는다
3. 코드 트랜스폼 (ts-jest)
- import ArticleList from "./ArticleList"
- TypeScript / TSX 문법을 그대로 Node가 이해할 수 없으니,
- ts-jest가 런타임에 해당 모듈을
- TypeScript 컴파일러(api)로 트랜스파일 → JavaScript
- JSX → React.createElement 호출로 변환
- (이 변환은 메모리상에서만 일어나며, 디스크에 .js 파일을 생성하지 않습니다)
4. 테스트 환경 세팅 (jsdom)
- 각 워커는 jsdom 인스턴스를 띄워
- global.window, global.document, global.navigator 등을 제공
- 브라우저 API(querySelector, createElement 등) 사용 가능
- beforeEach 단계에서 jsdom의 document.body.innerHTML = "" 로 DOM 초기화
5. 테스트 코드 평가 (Module Load)
테스트 파일 최상단의 import 구문이 실행되어…
import { render, screen, within } from "@testing-library/react";
import { ArticleList } from "./ArticleList";
import { items } from "./fixture";
- React Testing Library의 헬퍼 함수들
- 실제 <ArticleList> 컴포넌트 구현
- fixture.ts 에 정의된 테스트용 데이터
를 워커가 로드해 메모리에 올립니다.
6. 테스트 함수 실행
각 test(...) 블록은 아래와 같은 순서로 실행됩니다.
test("제목을 표시한다", () => {
// 1) render: ReactDOM.createRoot(container).render(...)
render(<ArticleList items={items} />);
// 2) DOM 쿼리: screen.getByRole(...)
const heading = screen.getByRole("heading", { name: "기사 목록" });
// 3) Assertion: toBeInTheDocument()
expect(heading).toBeInTheDocument();
});
- render()
- 가상의 <div data-testid="root"> 같은 컨테이너를 만들고
- React 18 기준 createRoot → root.render()
- 여러분의 컴포넌트를 jsdom(document.body)에 “마운트”
- screen/within 쿼리
- 내부적으로 document.body.querySelectorAll 또는
aria-query 라이브러리를 사용해 - 역할(role), 텍스트, 테스트 iD 등으로 노드를 찾아 반환
- 내부적으로 document.body.querySelectorAll 또는
- expect + Matcher
- expect(node).toBeInTheDocument() 같은 matcher가
- 실제로 node !== null 과 같은 조건을 검사
- 조건 불일치 시 에러를 던져 해당 테스트만 FAIL
- cleanup (자동)
- React Testing Library는 각 테스트 후 unmount() 와
document.body.innerHTML = "" 를 호출해 - 이전 테스트 렌더링 흔적을 제거
- React Testing Library는 각 테스트 후 unmount() 와
7. 스냅샷 비교
test("Snapshot…", () => {
const { container } = render(<ArticleList items={items} />);
expect(container).toMatchSnapshot();
});
- container 안의 DOM 트리를 문자열로 직렬화
- __snapshots__/ArticleList.test.tsx.snap 파일과 비교
- 다르면 FAIL → 콘솔에 diff 표시
- 의도된 변경이면 jest -u 로 스냅샷 갱신
8. 리포팅 & 종료
- 워커 프로세스가 PASS/FAIL 결과를 마스터 프로세스에 전달
- 콘솔에 각 테스트의 성공·실패, 실행 시간, 전체 요약 출력
- (watch 모드라면 파일 변경을 감시하면서 반복)
- 마지막에 Node 프로세스가 종료
요약
- Node + Jest CLI 가 설정 읽고 워커 띄움
- ts-jest 가 TSX → JS로 변환
- jsdom 가상 브라우저 환경 생성
- render() 로 React 컴포넌트 마운트
- screen/within 으로 DOM 검증
- expect 가 어설션 수행
- cleanup → 다음 테스트로
- 스냅샷 비교(해당 테스트에 있을 때)
- 최종 PASS/FAIL 보고
이 모든 과정이 실제 브라우저가 아니라 jsdom 위에서, Node 프로세스 내부에서 일어나며, 여러분이 터미널에 입력한 npx jest 하나로 자동으로 관리됩니다.
- 추가 설명
- render()
- jsdom 환경의 document.body 안에 실제 DOM 트리를 만듭니다.
- screen → document.body
- 전역 쿼리 함수(getByRole, getByText 등)를 screen 으로 묶어 제공합니다.
- getByRole("list")
- document.body.querySelectorAll('[role="list"], ul') 같은 내부 로직으로 <ul>을 찾고 반환
- within(list)
- list 요소를 “새로운 root”로 삼아 다시 쿼리 유틸리티 집합을 생성
- within(list).getAllByRole("listitem")
- list.querySelectorAll('[role="listitem"], li') 같은 내부 로직으로 <li>만 조회
- 어설션 (expect(…).toHaveLength(3))
- 반환된 배열 길이를 검사, 부족하거나 많으면 테스트 실패
- screen:
- 문서 전체에서 요소를 찾을 땐 기본으로 사용
- 편리하고 가독성도 좋습니다.
- within:
- 문서에 동일한 요소(또는 role)가 여러 개 있을 때
- 특정 컨테이너 내부만 검사하고 싶을 때
728x90
'리액트' 카테고리의 다른 글
FormTube - 헬스 자세 코칭 동영상 사이트 개발 과정 정리 - 1 - 기본 인증 구현 과 레이아웃 setting (0) | 2025.06.03 |
---|