[RTL] React Testing Library 도입기(CRA + typescript) FEAT. Enzyme

apro_xo·2022년 12월 4일
0
post-thumbnail

Enzyme vs React Testing Library

React Testing Library는 Jest를 기반으로 만들어진 테스팅 라이브러리이다.
CRA를 통해 프로젝트를 만든다면, 별도의 설치 없이 바로 사용할 수 있다.
Jest 기반이기 때문에 Jest 또한 설치할 필요가 없다.

React Testing Library가 각광 받기 이전에는 Enzyme을 주로 사용했다고 한다. Enzyme과 RTL의 차이가 뭘까?

1. 구현 주도 vs 행위 주도🔥

import React from 'react';

const Temp = () => {
  return(
    <h1>안녕하세요</h1>
  )
}

위의 컴포넌트를 테스트 한다고 가정하자.

Enzyme은 렌더링 된 <h1>안녕하세요</h1>가 h1 태그로 이루어진게 맞는지를 테스트 한다. 개발자 관점에서 테스트를 진행한다.

그리고 이를 구현 주도 테스트(Implementation Driven Test)라고 한다.

반면, RTL은 h1태그로 이루어진게 맞는지를 보는 것이 아니라 안녕하세요 라는 텍스트가 화면에 제대로 출력이 되었는지를 테스트 한다. 사용자 관점에서 테스트를 진행한다고 보면 되겠다.

이를 행위 주도 테스트(Behavior Driven Test)라고 한다.

사용자는 안녕하세요라는 텍스트가 div 태그로 이루어졌는지, h1 태그로 이루어졌는지 알 필요가 있을까? 없다❌

안녕하세요라는 텍스트가 사용자의 화면에 정상적으로 출력이 되었는지의 여부가 더 중요하다. RTL은 사용자 친화적인 테스트를 진행한다.

프로젝트에 RTL 도입

도입하면서 겪었던 에러, 해결한 방법 등의 기록이다.

1. typescript 설정

1-1. babel 설정

참고: https://jestjs.io/docs/getting-started

npm install --save-dev babel-jest @babel/core @babel/preset-env @babel/preset-react

npm으로 위의 목록들을 설치한다.

1-2. babel.config.json

{
	"presets": [["@babel/preset-env"],
                "@babel/preset-react"]
}

babel.config.json에 위의 코드를 추가한다.

1-3. typescript babel 설정

npm install --save-dev @babel/preset-typescript

위의 명령어를 입력하여 디펜던시에 추가한 후 babel.config.json을 아래와 같이 수정한다.

{
	"presets": [["@babel/preset-env"],
                "@babel/preset-react",
                "@babel/preset-typescript"]
}

2. MemoryRouter

import { render } from '@testing-library/react';
import App from '../App';
describe('테스트코드 테스트', () => {
	test('렌더링 테스트', () => {
		render(
          <App />
		).debug();
	});
});
// app.tsx
(...생략)
return (
  (...생략)
  <Routes>
    <Route path="/" element={<Navigate to="/viewer/topheadline" />} />
  	<Route path="/viewer/topheadline" element={<Viewer />} />
    <Route path="/viewer/:category" element={<Viewer />} />
    <Route path="/favorite/viewer" element={<FavoriteViewer />} />
   </Routes>
	);
(...생략)
};
(...생략)

app.tsx가 렌더링이 잘 되는지 간단하게 테스트를 해보기 위해 테스트 코드를 작성하였다. app.tsx는 위의 코드를 참고하면 된다.

app.tsx를 보면, react-router-dom을 사용하여 페이지별로 라우팅을 하고 있다.

테스트를 돌려보면 엄청나게 긴 에러가 발생한다.

우리가 react-router-dom을 사용하기 위해 index.tsx에서 BrowserRouter로 App 컴포넌트를 감싼 후 사용하는데, App 컴포넌트 렌더링을 테스트할 때는 브라우저 환경을 사용하여 테스트를 하는 것이 아니기 때문에 react-router-dom에서 제공하는 MemoryRouter를 사용하여 감싸주어야한다.

아래와 같이 테스트 코드를 수정하면 된다.

import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
describe('테스트코드 테스트', () => {
	test('렌더링 테스트', () => {
		render(
			<MemoryRouter>
              <App />
			</MemoryRouter>
		).debug();
	});
});

3. redux Provider

RTL을 적용시킨 프로젝트는 redux toolkit을 사용하고 있는데, 테스트를 진행하니 Provider로 감싸주어야한다는 에러가 발생했다.

그래서 테스트 코드에서도 index.tsx와 동일하게 Provider를 사용하여 감싸주었더니 해결되었다.

import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from '../redux/configStore';

describe('테스트코드 테스트', () => {
	test('렌더링 테스트', () => {
		render(
			<MemoryRouter>
				<Provider store={store}>
					<App />
				</Provider>
			</MemoryRouter>
		).debug();
	});
});

4. axios import 설정

App 컴포넌트를 테스트 코드에서 렌더링하는 과정에서 아래와 같은 에러가 발생했다.

axios를 import하는 과정에서 ES6 문법인 import를 사용할 수 없다는 것이다.

기본적으로 Jest는 import/export를 사용할 수 없고 require를 통해 모듈을 import해야한다. ES6모듈을 지원하지 않기 때문이다.

그래서 Jest에서 import/export를 사용하기 위해 알아보고 수정하였지만 해결하지 못하였다.

이 과정에서 이상한 점을 발견했다. 다른 모듈을 import/export를 사용하는 것은 에러 없이 테스트가 통과되는데, axios를 import 하는 것에서만 저런 에러가 발생하였다.

방향을 바꿔 알아본 결과 스택오버플로우를 통해 해결할 수 있었다.

// package.json
(...생략)
"jest": {
  "moduleNameMapper": {
    "axios": "axios/dist/node/axios.cjs"
  }
}

위 코드를 package.json에 추가하여 사용하니 axios에 대한 import 오류가 더 이상 발생하지 않았다.

stackoverflow: https://stackoverflow.com/questions/73958968/cannot-use-import-statement-outside-a-module-with-axios

profile
유능한 프론트엔드 개발자가 되고픈 사람😀

0개의 댓글