React Testing Library는 Facebook에서 공식적으로 사용을 권장하는 리액트 테스트 도구이다. 이 라이브러리는 사용자가 컴포넌트를 사용하는 것처럼 테스트를 작성할 수 있도록 설계되어있다.
React Testing Library는 기본적으로 cra로 react를 설치하면 같이 설치가 된다. 그럼 한번 사용법을 알아보자
초기 세팅
먼저, 새로운 React 프로젝트를 만들어보자. 이 포스팅에서는 타입스크립트를 이용했다.
$ npx create-react-app react-testing --template typescript
or
$ yarn create react-app react-testing --template typescript
설치가 완료 되었으면 App.test.tsx 파일을 지워주고
테스트를 진행하기 위한 Counter 컴포넌트를 아래처럼 만들어주자.
src/components/Counter.tsx
import React, { ReactElement } from "react";
interface CounterProps {
count: number;
onIncrease: () => void;
onDecrease: () => void;
}
function Counter({
count,
onDecrease,
onIncrease,
}: CounterProps): ReactElement {
return (
<div>
<h1>Counter</h1>
<button onClick={onIncrease}>증가</button>
<h3>{count}</h3>
<button onClick={onDecrease}>감소</button>
</div>
);
}
export default Counter;
App 컴포넌트에서 Counter의 로직을 작성해주고 불러와주자
src/App.tsx
import React, { useState } from "react";
import Counter from "./components/Counter";
function App() {
const [count, setCount] = useState(0);
const onIncrease = () => setCount(count + 1);
const onDecrease = () => setCount(count - 1);
return (
<div>
<Counter count={count} onDecrease={onDecrease} onIncrease={onIncrease} />
</div>
);
}
export default App;
테스팅
그럼 카운터 컴포넌트를 테스팅을 해보겠다.
components 폴더 내부에 __test__라는 폴더를 만들고 Counter.test.tsx라는 파일을 만들어 주자.
Counter.test.tsx 파일에 아래와 같이 적어주고 터미널에 yarn test or npm run test를 입력해보자.
import { render } from "@testing-library/react";
const CounterProps = {
count: 0,
onIncrease: jest.fn(),
onDecrease: jest.fn(),
};
describe("<Counter />", () => {});
CounterProps는 Counter 컴포넌트에 넣어줄 props들이다. 여기서 jest.fn()은 실제 함수를 넣어주는 것이 아닌 가짜 함수를 넣어주는 것이다.
여기서 가짜 함수를 넣어주는 이유는 React-testing-library로 함수의 로직을 테스트 하는 것이 아닌, 사용자 관점에서 컴포넌트가 동작하는지를 보기 위한 것이기 때문에, 로직이 없는 가짜 함수를 넣어줘도 상관없기 때문이다.
테스트 케이스는 다음과 같다.
1) 화면에 'Counter' 라는 텍스트가 보이는지 테스트
2) 증가 버튼을 클릭했을 때 onIncrease 함수가 실행되는지 테스트
3) 감소 버튼을 클릭했을 떄 onDecrease 함수가 실행되는지 테스트
1) 화면에 'Counter'라는 텍스트가 보이는지 테스트
import { render, screen } from "@testing-library/react";
import Counter from "../Counter";
const CounterProps = {
count: 0,
onIncrease: jest.fn(),
onDecrease: jest.fn(),
};
describe("<Counter />", () => {
test("화면에 'Counter'라는 텍스트가 보이는지 테스트", () => {
render(<Counter {...CounterProps} />);
const text = screen.getByText("Counter");
expect(text).toBeInTheDocument();
});
});
screen.getByText("Counter")는 화면에서 Counter라는 텍스트를 가지고 있는 HTMLElement를 찾아서 text라는 변수에 넣어준다.
expect(text).toBeInTheDocument()는 방금 저장한 HTMLElement가 Counter 컴포넌트 안에 있는지 테스트해준다.
만약 정확한 "Counter"를 찾는 것이 아닌 "Coun"을 포함하고 있는 텍스트를 찾고 싶을 경우 아래처럼 정규식을 사용하면 된다.
const text = screen.getByText(/Count/i);
expect(text).toBeInTheDocument();
2) 증가 버튼을 클릭했을 때 onIncrease 함수가 실행되는지 테스트
import { render, screen } from "@testing-library/react";
import Counter from "../Counter";
const CounterProps = {
count: 0,
onIncrease: jest.fn(),
onDecrease: jest.fn(),
};
describe("<Counter />", () => {
test("화면에 'Counter'라는 텍스트가 보이는지 테스트", () => {...});
test("증가 버튼을 클릭했을 때 onIncrease 함수가 실행되는지 테스트", () => {
render(<Counter {...CounterProps} />);
const button = screen.getByRole("button", { name: "증가" });
button.click();
expect(CounterProps.onIncrease).toHaveBeenCalled();
});
});
getByRole은 컴포넌트에서 Element를 가져오는 메서드이다. "button" 태그의 name이 "증가"인 Element를 불러와서
button.click()으로 실행시켰을 때 onIncrease 함수가 실행되는지 체크하는 테스트 케이스이다.
getByRole의 자세한 옵션은 여기서 볼 수 있다.
3) 감소 버튼을 클릭했을 때 onDecrease 함수가 실행되는지 테스트
감소 테스트는 증가와 거의 유사하다.
import { render, screen } from "@testing-library/react";
import Counter from "../Counter";
const CounterProps = {
count: 0,
onIncrease: jest.fn(),
onDecrease: jest.fn(),
};
describe("<Counter />", () => {
test("화면에 'Counter'라는 텍스트가 보이는지 테스트", () => {...});
test("증가 버튼을 클릭했을 때 onIncrease 함수가 실행되는지 테스트", () => {...});
test("감소 버튼을 클릭했을 떄 onDecrease 함수가 실행되는지 테스트", () => {
render(<Counter {...CounterProps} />);
const button = screen.getByRole("button", { name: "감소" });
button.click();
expect(CounterProps.onDecrease).toHaveBeenCalled();
});
});
이렇게 간단하게 Counter 컴포넌트로 테스트를 해봤다.
다음 포스팅에서는 react에서 custom hooks을 만들었을 때 custom hooks에 대해 테스팅을 해보겠다.
'React' 카테고리의 다른 글
React 18 useDeferredValue와 useTransition 이란? (0) | 2023.05.28 |
---|---|
React Testing Library를 이용한 Custom Hooks 테스팅 (1) | 2022.03.28 |
[컴포넌트 재활용하기] - Button (2) | 2022.02.19 |
나는 리액트를 어떻게 설계할 것인가? (8) | 2022.02.14 |
Recoil에서 Redux로 마이그레이션 하게 된 이유 (1) | 2022.01.16 |
댓글