티스토리 뷰
[Next Test] Next Js 에서 Jest와 React Testing-Library로 테스트 환경 설정하기 ( 기초 )
직역 2022. 4. 24. 01:18Next js 테스트 환경 설정하기
Next js 에서 테스트환경을 만들기 위한 방법중 하나로 Jest와 React Testing-Library 를 사용합니다.
Jest와 React Testing Library는 단위 테스트(Unit Testing) 에서 함께 자주 사용된다고 합니다.
이번 공부의 목적은 테스트 환경을 설정하는데 있어 구체적인 사항은
따로 공부를 진행하고 기초적인 세팅만 다루려고 합니다.
패키지 설치하기 ( Jest , Testing Library )
따로 설치하기
$ npm install --save-dev @testing-library/jest-dom
$ npm install --save-dev @testing-library/react
$ npm install --save-dev babel-jest
$ npm install --save-dev jest
한번에 설치하기
$ npm install --save-dev jest @testing-library/jest-dom @testing-library/react babel-jest
Jest 설정 with babel-jest ( jest.config.js )
루트 최상위 경로에 jest.config.js 파일을 생성한 뒤 다음 스크립트를 추가해줍니다.
Next.js 용 Jest를 구성하는 데 권장되는 옵션들입니다.
// jest.config.js
module.exports = {
collectCoverageFrom: [
'**/*.{js,jsx,ts,tsx}',
'!**/*.d.ts',
'!**/node_modules/**',
],
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)$',
],
}
스타일시트 및 이미지 가져오기 처리 ( 정적 자산 처리 )
테스트를 할 때에 스타일시트와 이미지는 테스트에 사용되지 않지만 가져오면 오류가 발생할 수 있어 Mocked 해야한다고 합니다.
*Mock 이란? : 실제 객체를 만들기에는 비용과 시간이 많이 들거나 의존성이 길게 걸쳐져 있어 제대로 구현하기 어려울 경우, 가짜 객체를 만들어 사용하는 것
__mocks__
루트 최상위에 "__mocks__" 폴더를 생성해줍니다.
그리고 fileMock.js 와 styleMock.js 파일을 내부에 생성해줍니다.
mocks 에 관련된 내용은 구조만 만들고 추후 공부를 진행하려합니다.
// __mocks__/fileMock.js
module.exports = {
src: '/img.jpg',
height: 24,
width: 24,
blurDataURL: 'data:image/png;base64,imagedata',
}
// __mocks__/styleMock.js
module.exports = {}
/선택사항/
jest-dom 을 통해 사용자 지정 매처로 Jest 확장
테스트를 더 쉽게 작성할 수 있도록 하는 사용자 지정 매처 세트가
'@testing-library/jest-dom' 에 포함되어 있습니다.
다음과 같은 옵션을 추가하면 사용할 수 있습니다.
jest.config.js 파일에 추가
- 아래의 옵션은 next js jest 추천 설정에 포함되어있는 스크립트입니다.
// jest.config.js
setupFilesAfterEnv: ['<rootDir>/jest.setup.js']
jest.setup.js 파일에 추가
// jest.setup.js
import '@testing-library/jest-dom/extend-expect'
모듈 절대 경로 별칭 ( Aliases )
파일을 import 할 때에 상대경로로 불러오거나 절대 경로를 통해서 불러오게 되는데,
해당 경로에 별칭을 주어서 더 쉽게 가져오는 방법이 있습니다.
타입스크립트를 사용하면 tsconfig.json에,
아니면 jsconfig.json 에 다음 컴파일러 옵션을 작성해줍니다.
// tsconfig.json or jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/components/*": ["components/*"]
}
}
}
그리고 jest.config.js 에 다음 옵션을 추가해줍니다.
- 아래의 옵션은 next js jest 추천 설정에 포함되어있는 스크립트입니다.
// jest.config.js
moduleNameMapper: {
'^@/components/(.*)$': '<rootDir>/components/$1',
}
start jest
jest 테스트 시작을 호출하는 스크립트가 필요합니다.
package.json 의 "scripts"에 "jest --watch" 스크립트를 추가해줍니다.
jest 만 넣으면 npm run test 를 통해서 테스트가 1번 이루어 지지만,
--watch 옵션을 넣게되면 파일이 변경되면 테스트를 다시 실행합니다.
// package.json
{
....
"scripts": {
....
"test": "jest --watch",
}
....
}
테스트를 위한 폴더/파일 구성
다음은 테스팅 구조를 만들어보겠습니다.
루트 최상위 폴더에 __tests__ 폴더를 만들어줍니다.
그리고 그 안에 index.test.tsx 파일을 생성해줍니다.
// __tests__/index.test.jsx
import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
describe('테스트', () => {
it('테스트 내용(case)', () => {
render('렌더링 될 컴포넌트')
const test = '테스트 할 내용';
expect(test).toBeInTheDocument()
})
})
간단한 테스트 진행
간단한 테스트를 위해 pages 폴더에 testing.tsx 페이지를 만들어주고 다음과 같이 스크립트를 작성해줍니다.
// pages/testing.tsx
import { NextPage } from 'next';
const Testing: NextPage = () => {
return (
<div>
<p>테스팅 페이지</p>
</div>
);
};
export default Testing;
마찬가지로 index.test.tsx 파일도 수정해줍니다.
다음 getByText() 메서드는 매개변수로 넘긴 텍스트를 해당 페이지에 있는지 찾게되고,
toBeInTheDocument() 메서드는 받은 테스트 값이 해당 문서에 랜더링된 화면에 존재하는지 테스트를 합니다.
// __tests__/index.test.tsx
import { render, screen } from '@testing-library/react';
import Testing from '@/pages/testing';
describe('Home', () => {
it('renders a Testing', () => {
render(<Testing />);
const text = screen.getByText(/테스팅 페이지/);
expect(text).toBeInTheDocument();
});
});
위와 같이 스크립트를 다 작성했으면, npm run test를 통해서 테스트를 해봅니다.
다음과 같이 테스트가 통과( PASS ) 되었다는 메세지와 함께 해당 테스트 정보들이 출력이 됩니다.
그렇다면 이번엔 getByText() 매개변수 /테스팅 페이지/ 를 다음과 바꿔봅니다. ===> /홈 페이지/
const text = screen.getByText(/홈 페이지/);
그리고 테스트 결과를 확인해봅시다. ( --watch 모드 덕분에 파일을 저장하면 바로 테스트 결과를 확인 가능합니다. )
다음과 같이 "테스트가 통과되지 못했다( FAIL )" 라고 나옵니다.
그리고 어느 부분에서 테스트가 실패했는지 표시되게 됩니다.
snapshot
그리고 선택적으로 해당 테스트에서 사용된 컴포넌트가 예기치 않게 변경되는 사항을
추적하기 위해서 snapshot 이라는 것을 추가해 줄 수 있습니다.
__tests__ 폴더에 snapshot.tsx 파일을 생성하고 다음 스크립트를 작성해줍니다.
// __tests__/snapshot.tsx
import { render } from '@testing-library/react';
import Testing from '@/pages/testing';
it('renders Testing unchanged', () => {
const { container } = render(<Testing />);
expect(container).toMatchSnapshot();
});
그리고 테스트를 실행해보면,
다음과 같이 __snapshots__ 폴더와 snapshot.tsx.snap 이라는 파일이 자동적으로 생성이 되고 내부엔 다음과 같이 스크립트가 작성이 되어있습니다.
// __tests__/__snapshots__/snapshot.tsx.map
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders Testing unchanged 1`] = `
<div>
<div>
<p>
테스팅 페이지
</p>
</div>
</div>
`;
이제 테스트 할 때에 Testing 페이지의 컴포넌트가 조금이라도 변경이 되고 테스트가 실행이 되면,
다음과 같이 snapshot이 실패되었다고 화면에 나오게 됩니다.
컴포넌트를 새로 수정하고 테스트를 하려면 기존에 생성된 snapshot을 제거하고 테스트를 진행 해야합니다.
이번 공부의 목적은 테스트 환경을 설정하는것이므로,
테스트를 어떻게 하는지에 대한 내용은 다음 공부에 진행을 하려합니다.
참고
Next Js 테스트 공식 문서
https://nextjs.org/docs/testing#setting-up-jest-with-the-rust-compiler