Next.js 환경에서 Jest & React Testing Library 사용하기

BinaryWoo_dev·2023년 2월 26일
1

리액트 테스트

목록 보기
1/5

	시작하기에 앞서 이 포스트 내용은 Next.js 의 공식 문서를 참조하여 기록한 것임을 알립니다.

서론


JestRTL(React Testing Library)유닛테스트를 위해 흔히 같이 사용된다.

다음과 같이 Next.js 프로젝트 환경에서 Jest를 사용할 수 있는 세 가지 환경 설정 방법이 있다.

  • Nextjs 공식 문서에 나와있는 quickstart 명령어 사용
  • Next.js Rust Compiler 를 사용
  • Babel 을 사용

하지만, 이번 페이지에서는 quickstart와 Babel 을 통해 사용하는 방법에 대해서만 자세히 알아볼 것이다.

Jest 기반의 Next.js 앱 프로젝트 환경 구축하기


quickstart 명령어로 Next.js + Jest 생성

#임시로 패키지를 설치하고 싶을 때
$npx create-next-app --example with-jest with-jest-app

# yarn 패키지 매니저 사용 시
$yarn create next-app --example with-jest with-jest-app

# npm 패키지 매니저 사용 시
$npm create next-app --example with-jest with-jest-app

Babel을 사용하여 Next.js + Jest 생성

Next.js 프로젝트 앱이 생성된 이후, Jest 를 사용하려면 아래의 패키지들을 개발 전용 설치 옵션으로 설치해줘야 한다.

(단, 해당하는 프로젝트의 Next.js version ≥ 12.x.x 일 경우, 기본으로 내장되어 있기 때문에 따로 설치할 필요가 없다.)

  • jest-environment-jsdom
  • @testing-library/react
  • @testing-library/jest-dom

설치

# yarn 패키지 매니저 사용 시
$yarn add --dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom

# npm 패키지 매니저 사용 시
$npm install --save-dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom

환경 설정

프로젝트의 루트 디렉터리에 jest.config.js 파일을 만들고 다음을 추가한다.
(Jest 공식 문서에서 각 구성 옵션에 대한 설명을 자세히 확인할 수 있다.)

// jest.config.js
module.exports = {
  collectCoverage: true,
  // on node 14.x coverage provider v8 offers good speed and more or less good report
  coverageProvider: 'v8',
  collectCoverageFrom: [
    '**/*.{js,jsx,ts,tsx}',
    '!**/*.d.ts',
    '!**/node_modules/**',
    '!<rootDir>/out/**',
    '!<rootDir>/.next/**',
    '!<rootDir>/*.config.js',
    '!<rootDir>/coverage/**',
  ],
  moduleNameMapper: {
    // Handle CSS imports (with CSS modules)
    // https://jestjs.io/docs/webpack#mocking-css-modules
    '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',

    // Handle CSS imports (without CSS modules)
    '^.+\\.(css|sass|scss)$': '<rootDir>/__mocks__/styleMock.js',

    // Handle image imports
    // https://jestjs.io/docs/webpack#handling-static-assets
    '^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$/i': `<rootDir>/__mocks__/fileMock.js`,

    // Handle module aliases
    '^@/components/(.*)$': '<rootDir>/components/$1',
  },
  // Add more setup options before each test is run
  // setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'],
  testEnvironment: 'jsdom',
  transform: {
    // Use babel-jest to transpile tests with the next/babel preset
    // https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
    '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
  },
  transformIgnorePatterns: [
    '/node_modules/',
    '^.+\\.module\\.(css|sass|scss)$',
  ],
}

스타일시트 및 이미지 가져오기 처리

stylesheet와 image는 테스트에는 사용되지 않지만 가져오면 오류가 발생할 수 있기 때문에 모의로 만들어야할 필요가 있다.

프로젝트의 루트 디렉터리에 __mocks__ 폴더를 생성 후, 폴더 안에 아래의 두 파일들을 생성한다.

  • fileMock.js
  • styleMock.js
// __mocks__/fileMock.js
module.exports = {
  src: '/img.jpg',
  height: 24,
  width: 24,
  blurDataURL: 'data:image/png;base64,imagedata',
}
// __mocks__/styleMock.js
module.exports = {}

(static assets 처리에 대한 자세한 정보는 Jest 공식 문서에서 확인할 수 있다.)

선택 사항: Custom matcher을 생성하여 Jest 확장하기

toBeInTheDocument() 매처가 테스트 작성을 더 쉽게 할 수 있게 해주는 것처럼 @testing-library/jest-dom에는 테스트를 더 쉽게 작성할 수 있는 편리한 커스텀 매처 세트가 포함되어 있다.

jest.config.js 파일에 다음과 같은 옵션을 추가한다면 모든 test 파일에서 custom matcher 을 import하여 사용할 수 있다.

// jest.config.js
setupFilesAfterEnv: ['<rootDir>/jest.setup.js']

위에 옵션 코드를 추가한 후 다음과 같이 jest.setup.js 파일에서 import 한다.

// jest.setup.js
import '@testing-library/jest-dom/extend-expect'

각각 테스트를 실행하기 전에 더 많은 설정 옵션들을 추가해야할 경우 보통 jest.setup.js 파일에 추가해야 한다.

선택 사항: 절대 가져오기 및 모듈 경로 별칭 설정하기

프로젝트에서 Module Path Aliases를 사용할 경우 jsconfig.json(tsconfig.json)에 설정되어 있는 파일 경로 옵션과 일치시켜 가져올 수 있도록 jest.config.js 을 구성해야 한다. (ex_ jest.config.js 내에 moduleNameMapper 옵션)

// tsconfig.json or jsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/components/*": ["components/*"]
    }
  }
}
// jest.config.js
moduleNameMapper: {
  '^@/components/(.*)$': '<rootDir>/components/$1', // 위의 jsconfig(tsconfig)의 paths와 일치시킴
}

Jest 테스트 실행 환경 만들기


test script 추가

watch mode 기반의 jest 실행 스크립트를 package.json에 추가한다.

// package.json

"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "test": "jest --watch" // --watch: test 파일이 업데이트 될 경우, 자동으로 재실행됨.
}

test 실행

$yarn test
$npm test

테스트 코드 작성하기 (예시)


이제 프로젝트를 테스트할 환경은 모두 준비가 되었다.
이제 Next.js 프로젝트의 루트 디렉터리에 __tests__ 폴더를 생성하고 해당 폴더 내부에 테스트 코드 파일들을 생성한다.

예를 들어 <Home/> 이라는 컴포넌트 구성 요소들 중 ‘제목’ 요소가 성공적으로 렌더링 되는지 테스트 하는 코드를 작성하면 아래와 같다.

제목 요소 렌더링 테스트

// __tests__/index.test.jsx

import { render, screen } from '@testing-library/react';
import Home from '../pages/index';
import '@testing-library/jest-dom';

describe('Home', () => {
	it('renders a heading', () => {
		render(<Home/>); // 1. Home 페이지 컴포넌트 렌더링
		
		// 2. 렌더링 된 화면(screen)dptj <name: 'welcome to next.js'> 라는 프로퍼티를 가지고 있는 
		//     <h$ name: 'welcome to next.js'>...</h$> 태그 요소를 heading 변수로 정의
		const heading = screen.getByRole('heading', { 
			name: /welcome to next\.js!/i,
		});

		// 3. heading 변수가 DOM 안에 존재하는지 테스트
		expect(heading).toBeInTheDocument();
	});
});

스냅샷 테스트

필요에 따라 스탭샷 테스트를 투가하여 구성요소에 대한 예기치 않은 변경 사항을 추적할 수 있다.

// /__tests__/snapshot.js

import { render } from '@testing-library/react';
import Home from '../pages/index';

it('render homepage unchanged', () => {
	const { container } = render(<Home />);
	expect(container).toMatchSnapshot();
})

*참고 : 테스트 파일은 page 디렉토리 내부에 포함되면 안된다. ( 테스트 파일은 page 디렉토리 내부의 모든 파일이 경로로 간주되기 때문)

profile
매일 0.1%씩 성장하는 Junior Web Front-end Developer 💻🔥

0개의 댓글