애플리케이션 개발에서 테스트는 코드의 품질을 높이고, 코드의 변경에 예상치 못한 버그를 방지할 수 있습니다.
테스트 환경 구축
yarn add -D jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom
프로젝트 루트에 jest.setup.js 파일 생성
import '@testing-library/jest-dom/extend-expect'
프로젝트 루트에 jest.config.ts 파일 생성
테스트 파일을 Typescript 로 작성하기 위해 ts-node를 설치합니다.
yarn add -D ts-node typescript jest
import type { Config } from 'jest'
import nextJest from 'next/jest.js'
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
/** @type {import('jest').Config} */
const config: Config = {
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jest-environment-jsdom',
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config)
작성 후 package.json 에 test 실행을 위한 스크립트를 추가합니다.
...
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint --dir src",
"format": "next lint --fix --dir src",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build",
"test": "jest"
},
...
근데 오류가 난다...SyntaxError: Cannot use import statement outside a module
좀 찾아보다가 아래처럼 수정하였습니다.
import type { Config } from 'jest'
const nextJest = require('next/jest')
const createJestConfig = nextJest({
dir: './',
})
const customJestConfig: Config = {
testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jsdom',
testEnvironmentOptions: {
html: '<html lang="zh-cmn-Hant"></html>',
url: 'https://jestjs.io/',
userAgent: 'Agent/007',
},
}
module.exports = createJestConfig(customJestConfig)
다시 실행한 결과 잘 실행됩니다.
테스트 예시
컴포넌트를 생성합니다.
import { ChangeEvent, useState } from 'react'
type InputProps = JSX.IntrinsicElements['input'] & {
label: string
}
export const Input = ({ label, ...rest }: InputProps) => {
const [text, setText] = useState<string>('')
const onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
setText(e.target.value)
}
const resetInputField = () => {
setText('')
}
return (
<div>
<label htmlFor={rest.id}>{label}</label>
<input {...rest} type='text' value={text} onChange={onInputChange} />
<button onClick={resetInputField}>Reset</button>
</div>
)
}
test 파일을 작성합니다.
첫 화면의 input 요소는 비워져있어야하는 test를 진행합니다.
import { Input } from '@/components/Input'
import { RenderResult, fireEvent, render, screen } from '@testing-library/react'
/**
* describe 함수를 사용하여 함수를 모은다. 여기서는 Input Component 의 테스트를 진행한다.
*/
describe('Input', () => {
let renderResult: RenderResult
/**
* beforeEach , afterEach 함수는 각 테스트 실행 전, 후의 처리를 기술합니다.
*/
// 각 테스트 케이스 전에 컴포넌트를 화면에 그리고, renderResult에 설정한다.
beforeEach(() => {
renderResult = render(<Input id='testInput' label='Test Input' />)
})
// 테스트 케이스 실행 후 화면에 그려진 컴포넌트를 unmount를 호출해 릴리스 합니다.
afterEach(() => {
renderResult.unmount()
})
it('첫 화면에서 input 요소는 비워져있어야 합니다.', () => {
// label이 Test Input 인 input 요소를 가져옵니다.
const inputNode = screen.getByLabelText('Test Input') as HTMLInputElement
// Input 요소의 표시가 비어있는지 확인한다.
expect(inputNode).toHaveValue('')
})
it('문자 입력 후 내용이 표시되는지 테스트', () => {
const inputText = 'Test Input Text'
const inputNode = screen.getByLabelText('Test Input') as HTMLInputElement
//fireEvent 를 사용해 input 요소의 onChange 이벤트를 트리거합니다.
fireEvent.change(inputNode, { target: { value: inputText } })
// input 요소에 입력한 텍스트가 표시되는지 확인한다.
expect(inputNode).toHaveValue(inputText)
})
it('reset 버튼이 클릭되면 입력 텍스트가 초기화되는지 테스트', () => {
const inputText = 'Test Input Text'
const inputNode = screen.getByLabelText('Test Input') as HTMLInputElement
fireEvent.change(inputNode, { target: { value: inputText } })
// 버튼을 받아온다
const buttonNode = screen.getByRole('button', {
name: 'Reset',
}) as HTMLButtonElement
// 버튼 Click
fireEvent.click(buttonNode)
//input요소가 Reset 됫는지 확인한다.
expect(inputNode).toHaveValue('')
})
})
테스트를 실행합니다.
yarn test
'React > NextJS' 카테고리의 다른 글
Nextjs Boilerplate 만들기 - 6 [React Hook Form 도입] (0) | 2023.07.20 |
---|---|
Nextjs Boilerplate 만들기 - 4 [Storybook 설정] (0) | 2023.07.11 |
CSR? SSR? SSG? ISR ? NextJS 에서 구현해 보자 (0) | 2023.07.05 |