최근에 react로 만든 어플리케이션에서 jest를 적용해야 했었습니다.
적용하면서 막혔던 부분들에 기록해 두려 합니다.
요약순서
1. 필요 라이브러리 설치
2. package.json 수정
2. jest config.js 설정
3. test 파일 작성
4. test 실행
cra with typescript 로 생성한 프로젝트에서
1. 필요 라이브러리 설치
yarn add -D jest @types/jest ts-jest
jest : javascript 테스트 프레임워크 입니다.
@types/jest : jest의 타입 정의를 포함하고 있는 라이브러리 입니다.
ts-jest : typescript로 작성된 프로젝트들을 테스트 할 수 있게 해주는 typescript 전처리 라이브러리 입니다.
2. package.json 수정
"scripts": {
....
"test": "jest" // coverage 옵션을 주고 싶으면 --coverage를 추가해주면 됩니다.
....
}
3. jest config.js 설정
package.json과 같은 depth에 jest.config.js 파일을 생성해 줍니다.
module.exports = {
testPathIgnorePatterns: ["<rootDir>/client/node_modules/"],
transform: {
"^.+\\.(js|jsx|ts|tsx)$": "ts-jest",
},
moduleNameMapper: {
"^src/(.*)$": "<rootDir>/src/$1",
},
testEnvironment: "jsdom",
};
testPathIgnorePatterns : 테스트 하지 않는 경로를 설정할 수 있습니다.
transform : "정규표현식" : "transformer" => 경로를 정규표현식으로 설정하고 transformer를 지정할 수 있습니다.
trasnformer는 source 파일들을 변환해주는 동기적으로 실행되는 함수를 제공해주는 모듈입니다.
babel (babel-jest) 과 typescript(ts-jest)를 설정할 수 있습니다.
저는 typescript를 파일내에 사용하였으므로 ts-jest를 설정해주었습니다.
babel은 적용해야할 boiler plate 코드들이 많다고 판단하여 적용하지 않았습니다.
moduleNameMapper : 정규표현식을 통해 경로의 이름과 실제 경로를 설정해줄 수 있습니다.
예시를 들어서 보여드릴게요.
위 이미지를 보면 첫번째 import문의 경우 상대경로가 아닌 src/utils 로 작성되어 있습니다.
이와 같이 사용할 수 있는 이유는 아래의 tsconfig.json에서 baseurl을 client 폴더로 설정해 주었기 때문입니다.
typescript compiler가 동작하게 될때 tsconfig.json의 baseurl을 root로 설정하여 src/utils를 찾는데 문제가 없기 때문입니다.
하지만 jest를 동작할때는 이야기가 다릅니다.
baseurl과 같은 설정이 없기 때문에 moduleNameMapper 옵션을 통해 src에 대한 위치를 지정해 주어야 합니다.
module.exports = {
...
moduleNameMapper: {
"^src/(.*)$": "<rootDir>/src/$1",
},
...
};
위와 같이 src 경로에 대한 위치를 지정해주어서 unittest를 진행할때 경로를 못찾는 경우가 없게 하였습니다.
저는 tsconfig.json에서 paths 설정을 자주 사용합니다.
실행파일 내에서 다른 파일들을 import할때 상대경로가 길어지는 경우를 절대경로로 바꾸어 좀 더 깔끔하게 가져올 수 있기 때문에 선호합니다.
paths 를 이용해 모듈들을 가져오고 jest를 사용할 때는 moduleNameMapper를 이용하면 에러 없이 사용할 수 있을것 같습니다.
testEnvironment : 테스팅 되는 환경을 정의 하여 줍니다. 기본값은 "node" 입니다. 만약에 웹앱과 같은 브라우저 환경에서 테스트 되어야 한다면 "jsdom" 옵션을 주면 됩니다.
node 환경으로 정의되어 있다면 브라우저 에서 제공하는 api들은 사용할 수 없게 되어집니다.
ex) document.createElement('div')
https://jestjs.io/docs/configuration#testenvironment-string
4. test 파일 작성
test 파일은 package.json 파일이 작성된 내부의 폴더라면 어느 곳이든 상관없습니다.
저는 이번 프로젝트에서는 기능별로 파일을 모아두는 방향으로 작업을 진행했어서 test 폴더를 생성후에 test파일을 생성하였습니다.
파일을 생성해 줄때는 ***.test.(ts|js|tsx|jsx)? 와 같이 생성해 주어야 합니다.
// Product.test.tsx
import { render, screen } from "@testing-library/react";
import { ThemeProvider } from "styled-components";
import { BrowserRouter } from "react-router-dom";
import ProductListCard from "../components/ProductListCard";
import { theme } from "../assets/styles/theme";
describe("ProductListCard", () => {
it("Product List Card", () => {
const product = {
id: 1645426258567,
name: "냉면용기(대)",
price: 83700,
imageUrl: "https://cdn-mart.baemin.com/goods/2/1556008840639m0.jpg",
};
render(
<BrowserRouter>
<ThemeProvider theme={theme}>
<ProductListCard {...product} />
</ThemeProvider>
</BrowserRouter>
);
const productCard = screen.getByText(product.name);
expect(productCard).not.toBeNull();
});
});
react 공식문서에서는 React Testing Library의 사용을 권장하고 있습니다. 사용자가 컴포넌트를 사용하는 것처럼 테스트를 작성할 수 있도록 설계되어있다는 이유에서 권장하고 있습니다.
저는 testing-library를 권장하는 이유를 jsdom 라이브러리를 통해 컴포넌트를 실제 브라우저 Dom을 기준으로 생성해줍니다.
그걸 쿼리 메소드를 통해 가져오고 jest의 메소드와 함께 사용할 수 있어 실제 사용자가 컴포넌트를 사용하는 것과 같이 테스트 할 수 있기 때문에 권장한다고 이해하였습니다.
저는 testing-library를 사용하였고
1. render를 통해 제가 작성한 컴포넌트를 렌더링시킨뒤에
2. screen 객체에서 제공하는 쿼리 메소드를 통해 제가 작성한 컴포넌트를 가져왔습니다.
3. jest의 expect 메소드를 통해 해당 컴포넌트가 정상적으로 생성되어 있는지를 확인하였습니다.
(jest와 testing library를 이용하여 원하는 테스트 시나리오의 테스트를 구현해보세요!!!)
https://testing-library.com/docs/queries/about/#screen
아래 링크는 jest의 버전이 27 혹은 그 이상일 경우에 testing library를 사용하기 위한 설정입니다.
jest 27 버전 이상에서는 jsdom이 기본 환경이 아니라서 jest.config.js에서 수정해 주어야 합니다.
module.exports = {
+ testEnvironment: 'jest-environment-jsdom',
// ... other options ...
}
https://testing-library.com/docs/react-testing-library/setup/#jest-27
render(
<BrowserRouter>
<ThemeProvider theme={theme}>
<ProductListCard {...product} />
</ThemeProvider>
</BrowserRouter>
);
render 내의 내용을 보면 제가 BrowserRouter, ThemeProvider를 제공해 준것을 확인할 수 있습니다.
BrowserRouter는 Routing을 위해 react-router-dom 라이브러리에서 제공하는 것이고
ThemeProvider는 styled-component 라이브러리에서 제공하는 것입니다. 저는 반응형 작업을 위해 theme를 추가하였습니다.
테스트를 위해 productListCard를 실행하면 컴포넌트 안에서 Link와 theme를 사용합니다.
이를 제공해주어야 테스트가 정상적으로 실행될 수 있습니다.
5. test 실행
이제 yarn test를 실행하여 테스트 해줍시다.
아래와 같은 화면을 확인할 수 있을 겁니다!!
--coverage 옵션을 주지 않으면 결과만 출력해줍니다!
'Frontend > React' 카테고리의 다른 글
제어 컴포넌트 vs 비제어 컴포넌트 (0) | 2022.03.03 |
---|---|
React twice render (0) | 2022.02.24 |
넘블챌린지 [Square Select Game] (0) | 2022.02.10 |
cannot get /path (0) | 2022.02.07 |
cra typescript 초간단 세팅 (0) | 2022.01.17 |