Render 관련 코드 구조
describe("Application 테스트", () => {
it("Application - UI Test ", () => {
render(
<ThemeProvider theme={customTheme}>
<FetchProvider>
<Application
match={{ params: { id: 120 } }}
goodsDataInit={{
title: "",
quantity: 0,
minQuantity: 10,
maxQuantity: 1000, // hooks 를 체크하기 위해서 init데이터를 설정한다.
}}
/>
</FetchProvider>
</ThemeProvider>,
{ wrapper: MemoryRouter }
);
// ...
material UI 특성상 theme 가 구동되기 때문에 ThemeProvider 를 감싸줘야 한다.
(참고 : Custom Render - 아예 test-util을 만들어서 wrapping 하는 방법도 있다.)
FetchProvider 도 감싸줘야 하며, Application 내부에서 match.params.id 를 사용하는데,
페이지를 전환하면서 전달한 게 아니라서, 임의로 props로 match 객체처럼 보여지게끔 전달해서 해결했다.
Provider들을 감싸는 이유는 Context API 에서 관리되는 store들이 이하 component들로 내려져야 하기 때문에 그러하다. (참고 : https://ko.reactjs.org/docs/context.html#api)
// in Router
<Route path={`${path}/:id/oooo/application`} component={SharingApplication}/>
// 주소상에 있는 id 값이 match.params.id 로 전달된다.
Hooks 테스트하기
api를 받았다 치고 하는 경우들 같은 경우, 꽤 많은 부분 state를 변경하는데. 이부분을 아래와 같이 초기값을 props로 설정해서 useState로 내려주면, 테스트를 굉장히 원활하게 진행하는데 유용한 방식 같다.
const Application = ({
match,
width,
goodsDataInit = {
title: "",
quantity: 0,
minQuantity: 0,
maxQuantity: 0,
},
}) => {
const [goodsData, setGoodsData] = useState(goodsDataInit);
return ()
}
참고 : 이 참고 경로에서 꽤 많은 도움을 얻었다. https://www.daleseo.com/react-hooks-testing-library/
Debug 관련 (package.json)
작업하다보면, 컴포넌트가 렌더가 안되는 경우가 있어서, 이를 보기 위해서 screen.debug()를 해서 렌더링이 어떻게 되는지 console.log를 해보는 경우가 있다.
근데 기본 값 설정 때문에 출력이 안되는 경우가 있었다. 이는 다음과 같이 해결했다.
// in package.json
"test": "DEBUG_PRINT_LIMIT=40000 react-scripts test",
// 프린트 되는 제한 Line수의 기본값을 바꾼다. (defaultValue : 7000)
// debug line을 더 늘려도 되지만.. 테스트하는 컴포넌트 단위를 바꾸는 게 나을 것 같다.
테스팅 코드
// static한 label 렌더 잘 되는지 확인
expect(screen.getByTestId("infoTag-title")).toHaveTextContent("나눔 물품:");
expect(screen.getByTestId("infoTag-total-quantity-label")).toHaveTextContent("총 지원 수량:");
expect(screen.getByTestId("infoTag-total-quantity")).toHaveTextContent(0);
// 신청서 출력하기 버튼 비활성화 체크
expect(screen.getByTestId("application-form-print-btn")).toBeDisabled();
// input, textarea 입력 & radio Button 클릭
const sharingTypeRadioBtn = screen.getByTestId("sharing-type-radio-btn");
fireEvent.click(sharingTypeRadioBtn);
const quantityInput = screen.getByTestId("quantity").querySelector("input");
fireEvent.change(quantityInput, { target: { value: 1 } });
const contentInput = screen.getByTestId("content-textarea");
fireEvent.change(contentInput, { target: { value: "test content" } });
// 신청서 출력하기 버튼 활성화 체크
expect(screen.getByTestId("application-form-print-btn")).toBeEnabled();
getByTestId 이후에 어떤 method를 chaining할지는 screen.debug()로 보면서 하는 수 밖에 없는 것 같다.
위 코드를 간단하게 설명하면 아래와 같다.
1. 컴포넌트에 값을 입력하는 event를 발생시킨다.
2. button이 정상적으로 비활성화에서 활성화로 바뀌는지 체크하는 테스트 코드이다.
테스트 ID를 쓰는 이유
getByTestId로 하는 이유는 기본적으로 getByText 같은 형태로 하면, 동적인 Text가 렌더된 Dom에 있을 경우, 체크하기가 좋다.
ByLabelText, ByText 등.. 다른 것도 많지만, 가능하면 TestId를 컴포넌트 내에 입력해두고, 사용하는 것이 좀 더 명확한 것 같다.
// 개별 컴포넌트에서는 아래와 같이 작성한해서 props로 내리고 나서
<BsButton testID="application-form-print-btn" />
// 관리하는 Atom에서 아래와 같이 작성하면 된다.
<Button data-testid={testID} />
개발 조직에서 보완하면 좋겠다 싶은 부분
가능하면, 기획자가 작성한 테스트 문서의 Test ID를 기준으로 같은 id를 사용하면 더 좋겠다는 생각이 든다.
그러면, 향후에 문제가 생겼을 때, 알아보기도 좋을 것 같으니까..
그러면, Storyboard (화면설계서) - 단위 테스트 or 시나리오 테스트 문서 - Test ID (in 테스트 코드) 간에 기본 골조가 있으면 가장 최상의 생산성을 구현해낼 수 있을 것 같다.
내가 원래 기획자 출신이라 그런지... 이런 생각들을 하게 되는 것 같다.
참고했던 자료
https://react-hooks-testing-library.com/usage/basic-hooks
https://testing-library.com/docs/example-react-router/#reducing-boilerplate
https://www.daleseo.com/react-hooks-testing-library/
'React & TypeScript > React' 카테고리의 다른 글
[React / Ant Design] Ant Design에서 Calendar Localization 하는 법 (0) | 2022.12.19 |
---|---|
[React] 프론트엔드 폴더 구조 방법론 정리 [펌 + 사견] (0) | 2022.12.14 |
[React / TypeScript] styled-components와 함께 사용하는 TypeScript에 대한 고찰 (feat.react) (1) | 2022.11.28 |
React useEffect (included api 호출) 가 있는 컴포넌트 분리 방법 (0) | 2022.04.29 |
Build 이후 흰 화면만 나오는 이유 (로컬 index.html 안열리는 이유, react-router, 파일 프로토콜, http 프로토콜) (0) | 2021.09.16 |
[React] cypress를 활용한 React 테스트 (feat. 시나리오 테스트, E2E Test) (0) | 2021.08.25 |
리액트 SEO - 검색엔진(네이버, 구글)에서 검색되도록 고치는 방법 / robots.txt (0) | 2021.07.20 |
댓글