react test 코드를 작성하는 방법에 대해서 알아봅시다.
우선 현업에서는 바쁘다는 이유로 테스트코드를 작성하지 않는 경우가 많은거 같고 나 또한 작성해 본 경험이 없습니다..
왜 테스트 코드를 작성을 해야되는 이유를 몇가지 알아봅시다.( 다들 아는 내용이지만....)
애츨리케이션의 코드품질 및 안정성을 위해
유지보수성 향상 (개발자의 자신감도 👍)
테스트 코드가 완전하게 커버되어 있다면 프로젝트 신뢰성이 높아지며 사용자에게 안정적인 어플리케이션을 제공함.
React Testing Library는 사용자 관점에서 테스트를 수행하며, 애플리케이션의 실제 사용자와 유사한 방식으로 상호작용합니다. 이는 사용자의 행동에 따른 애플리케이션의 동작을 테스트하는 데 매우 유용합니다. 또한, React Testing Library는 컴포넌트의 내부 구조에 의존하지 않으므로, 컴포넌트의 내부 구현이 변경되어도 테스트를 재작성하지 않아도 됩니다.
가상 DOM(Virtual DOM)을 사용하여 테스트를 수행합니다. 가상 DOM은 실제 DOM과 유사한 인터페이스를 제공하지만, 메모리 상에 존재하는 가짜 DOM입니다. 가상 DOM을 사용하여 컴포넌트를 렌더링하고, 이를 기반으로 테스트를 수행합니다.
우선 컴포넌트를 몇개씩 만들어보면서 테스트 코드를 작성해 볼 예정입니다. (반복숙달)
CRA로 리액트 프로젝트를 만들면 설치가 되어있는 상태이기 때문에 바로 테스트를 할 수 있습니다.
기본적으로 jest도 알아야 되지만 연습을 해보면서 설명이 필요한 부분은 최대한 상세하게 처음하는 사람도 알아보기 쉽게 작성을 해보겠습니다.
import React, { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
const handleIncrement = () => {
setCount(count + 1);
};
const handleDecrement = () => {
setCount(count - 1);
};
return (
<div>
<h2>Counter</h2>
<p>{count}</p>
<button onClick={handleIncrement}>+</button>
<button onClick={handleDecrement}>-</button>
</div>
);
}
우선 첫번째는 컴포넌트에서 어떤걸 테스트 해야될지 확인을 해야됩니다. 우선 버튼을 클릭하면 count가 증가/감소하는 간단한 컴포넌트이입니다.
저라면 1. 랜더링이 잘 되는지 2. 버튼 증가를 클릭했을때 3. 버튼 감소를 클릭했을때 정상적으로 카운트가 증가/감소가 되는지 테스트를 해볼껍니다.
npx create-react-app react-test-playgroud
로 프로젝트를 만들고
src > components > tests 이렇게 컴포넌트를 만들고 tests 폴더안에 컴포넌트를 테스트를 해보겠습니다. 리액트에서 .test.js/ .spec.js로 끝나면 Jest 나 다른 테스트러너드가 해당 파일을 자동으로 인식하여 테스트 코드를 실행합니다.
// Counter.test.js
import Counter from "../Counter";
import { fireEvent, render, screen } from "@testing-library/react";
import { act } from "react-dom/test-utils";
import userEvent from "@testing-library/user-event";
describe("Counter", () => {
it("render correctly", () => {
renderCounter();
expect(screen.getByText("Counter")).toBeInTheDocument();
});
it("increment count when the increment button is Clicked", () => {
renderCounter();
const button = screen.getByText("+");
fireEvent.click(button);
// act(() => {
// userEvent.click(button);
// });
expect(screen.getByText("1")).toBeInTheDocument();
});
it("decrement count when decrement button is clicked", () => {
renderCounter();
const button = screen.getByText("-");
fireEvent.click(button);
expect(screen.getByText("-1")).toBeInTheDocument();
});
});
function renderCounter() {
return render(<Counter />);
}
우선 코드를 작성할때 Given - When - Then 이런식으로 테스트코드를 작성을 해보면 처음 코드를 작성하는사람에게 도움이 됩니다.
어떤 상황이 주어졌때 - 어떤 동작이 수행 될 때 - 기대하는 결과 이런식으로 작성을 하면 됩니다..
우선 코드를 설명하기전 처음 보는 함수가 많을테니 간단하게 설명을 하고 넘어가겠습니다.
describe: 이 함수는 관련된 테스트들을 그룹화하는 역할을 합니다. 보통 기능 또는 컴포넌트에 대해 테스트 그룹화할떄 사용합니다.(로그인, 헤더 컴포넌트), 첫번째 이름으로 해당 코드 설명을 적고 두번째 부터 it을 활용해서 테스트 코드를 작성하면 됩니다.
it: 함수는 하나의 테스트를 정의하는 역할을 합니다. it 함수의 첫 번째 인자로는 해당 테스트의 이름을 지정하고, 두 번째 인자로는 실제 테스트 코드를 작성합니다. (test함수도 있는데 it이랑 기능적으로 똑같은 역할을 하고 이름이 더 직관적인면이 인거 같다.)
render: React 컴포넌트를 렌더링하는 함수입니다. 이 함수를 사용하여 테스트하고자 하는 컴포넌트를 렌더링하고, 해당 컴포넌트를 테스트할 수 있는 테스트 유틸리티 함수들을 반환합니다.
screen: 객체는 DOM 요소에 접근하고 검증하는 데 사용되는 객체입니다. 이 객체를 사용하여 요소를 찾고, 해당 요소가 존재하는지, 보이는지 등을 검증할 수 있습니다.
expect: 함수는 검증(assertion)을 수행하는 함수입니다. 이 함수는 특정 값을 검증하거나, 특정 조건을 만족하는지 검증하는 등 다양한 검증을 수행할 수 있습니다
fireEvent: DOM 이벤트를 트리거하는 함수입니다.
getByText: 이 함수는 DOM에서 특정 텍스트를 포함한 요소를 검색하는데 사용되어 집니다.
아래는 get, find , query에 설명에 대한 간략한 표입니다.
getByRole: 위에서 사용되어지지 않았지만 유용한 query, 요소의 role을 사용하여 해당 요소를 검색하는 함수. ex) .getByRole('button)
element role 확인하는 사이트
위에 함수에 대한 설명이 적혀져있기때문에 코드에 대한 설명은 하지 않고 저는 어떤식으로 테스트코드를 작성했는지 설명을 해보겠습니다.
첫번째로 보통 컴포넌트가 랜더링이 잘 되는지 작성을 했고, 2, 3번째는 버튼을 클릭했을때 정상적으로 count의 값이 변경이 되었는지 테스트 코드를 작성했습니다.
테스트 코드를 작성했으면 터미널에
npm run test
입력하여 테스트가 정상적으로 동작되었는지 확인을 합니다. 커버리지 테스트도 하고 싶다면
npm test -- --coverage --watchAll=false
를 입력하고 내가 만든 컴포넌트가 100% 테스트 커버리지가 되었는지 확인을 하면 됩니다.
간단하게 작성해보면서 감을 익혔고 계속 테스트 코드를 작성을 해보면서 감을 익히도록 해보겠습니다.