ET네 만물상 - GitHub Repository / 배포 링크
TDD를 경험해보았다.
프로젝트 끝까지 테스트를 신경쓰진 못 했다. 적당한 사용법과, 나중에 오래 운영할 프로젝트라면 TDD가 좋을 거 같다는 느낌?만 받았다..
테스트 주도 개발.
컴포넌트, 유틸 함수 등에 대해 테스트를 먼저 작성하고 그 테스트를 통과하는 코드를 작성하는 방식
리팩토링/기능 추가 등 소스코드를 추가/변경 할 때 테스트 통과 유무를 통해 문제를 발견할 수 있다
예를 들어 리팩토링을 한 후 테스트가 깨졌다면, 무언가 잘못 된 것이다..
먼저 TDD라는 걸 경험해보고자 하는게 목적이 컸다.
Jset / testing-library 를 사용했다.
초반 마크업을 먼저 작성하고, 그에 대한 테스트를 작성 후, 기능을 붙이면서 테스트 렌더링 관련 테스트를 통과하는지 확인했다
프로젝트를 진행하면서 컴포넌트가 늘어나고, 계속 변경되면서 테스트 주도가 아니라 컴포넌트를 위한 테스트 코드 다듬기를 하는거 같아서 중간부터는 테스트 코드 작성을 하지 않았다.
느낀 바로는, TDD를 위해서는 생각 이상으로 많은 시간을 들여야하고, 설계를 아주 자세하게해야 한다. 데이터 형태나 컴포넌트 트리, 상태관리를 어떻게 할지 (props전달 / 전역 상태 등..)을 모두 고려해야한다.
3주라는 시간 동안, 완성도라는 팀 목표에는 맞지 않는 거 같았고, 테스트를 어떤식으로 하는 거구나 감만 익히는 정도로 경험한 거 같다
자바스크립트 테스트 프레임워크
Test Runner / Test Mathcer / Test Mock 까지 통합으로 제공한다.
Jest에서 react 테스트를 위해 추가적으로 필요한 라이브러리
모든 테스트를 DOM 위주로 진행한다. 즉, 실제 HTML 마크업의 모습이 어떠한지 테스트하기 용이하다 (BEehavior Driven Test)
컴포넌트의 props/state를 조회하지 않고 컴포넌트의 기능이 똑같이 작동한다면, 컴포넌트의 내부 구현 방식이 바뀌어도 테스트가 실패하지 않는다
Enzyme 에 비해 필요한 기능만 지원해서 매우 가볍고, 일관적인 테스트 코드 작성을 할 수 있다.
src 디렉토리에 setUpTest.js|ts 파일을 생성해야한다
// Button.test.ts|tsx
describe("<Button />", () => {
it("should render component in document", () => {
// Given
const handleClick = jest.fn();
const { container } = render(
<Button {...buttonProps} onClick={handleClick} />
);
const children = screen.queryByText(CHILDREN);
// When
fireEvent.click(
screen.queryByRole("button") || screen.queryByRole("submit")
);
// Then
expect(container).toBeInTheDocument();
expect(children).toBeInTheDocument();
expect(handleClick).toHaveBeenCalledTimes(1);
});
이 테스트는 해당 버튼이 정상적으로 렌더링 되었는지 / 버튼 내의 텍스트는 정상인지 / 정상적으로 클릭 되는지를 테스트한다
Given은 테스트를 위해 준비하는 과정으로, 컴포넌트를 렌더하고, 렌더된 버튼 내부 텍스트 값을 가져오는 등의 동작이다
When은 실제로 테스트를 진행하는 과정이다. 컴포넌트 렌더나 내부 텍스트의 경우 When의 동작이 필요 없지만, 클릭 이벤트 같은 경우가 이에 해당한다
Then은 테스트를 검증하는 과정이다. Given/When의 동작과 실제 예상이 일치하는지 테스트한다.
특정 조건이 충족하는지 확인한다.
expect에 검사할 대상을 인자로 넣고 반환하는 객체(JestMatchers)의 메소드를 사용한다.
주로 toBe~ 의 형태를 띄고 있다.
<Wrapper data-testid="test__container"></Wrapper>
const queryClient = new QueryClient();
const AllTheProviders: FC = ({ children }) => {
return (
<ThemeProvider theme={theme}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</ThemeProvider>
);
};
const customRender = (
ui: ReactElement,
options?: Omit<RenderOptions, "wrapper">
) => render(ui, { wrapper: AllTheProviders, ...options });
export const expectText = (text: string) => {
expect(screen.queryByText(text)).toBeInTheDocument();
};
export * from "@testing-library/react";
export { customRender as render };
테스트 코드에서 render가 react-query 관련 에러가 발생해서 그 처리를 위해 따로 작성한 유틸이다.
Provider 관련을 함께 묶은 render 유틸이라고 보면 된다! 그 외에는 기존 testing-library와 같다.