
Facebook에서 권장하는 React 컴포넌트를 테스트 하기 위해 만들어진 도구이다.
기존의 테스팅 도구들은 사용자 입장에서 테스팅하기 보단, 해킹해서 테스팅하는 듯한 느낌을 주었다. 그러나 RTL은 사용자 입장에서 테스팅하는 느낌을 주는 테스팅 라이브러리이다.
웹 브라우저가 아닌 환경(Node.js 환경 등)은 window 전역 객체가 없다. 따라서 DOM에서 접근할 수 없으며 각 요소에 대한 접근과 조작이 불가능하다. 하지만 RTL은 가상의 window 객체를 제공하기 때문에 접근 및 조작이 가능한 것처럼 보이게 한다
-> window 객체가 필요한 document.createElement같은 구문도 동작이 가능하다.
이때 주의해야 할 점은, 브라우저에서 실행되는 느낌이 E2E 테스트에 가까운 느낌을 주나, 진짜 브러우저에서 실행되는 것이 아니기 때문에 E2E 테스트가 아니다
일반적으로 CRA에 내장되어 있어 따로 설치가 필요없으나, 개발 환경을 직접 설정한다면 설치해야 한다.
npm install --save-dev @testing-library/react @testing-library/dom
// TypeScript 사용 시
npm install --save-dev @testing-library/react @testing-library/dom @types/react @types/react-dom
yarn add --dev @testing-library/react @testing-library/dom
// TypeScript 사용 시
yarn add --dev @testing-library/react @testing-library/dom @types/react @types/react-dom
아래 예제는 Counter 컴포넌트를 테스트해보는 예제이다. 밑의 예제 코드에서 확인하고자 하는 항목은
- 컴포넌트가 렌더링 되는지
+버튼을 눌렀을 때 count가 증가하는지-버튼을 눌렀을 때 count가 감소하는지
// Counter.js
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const decrement = () => setCount(count - 1);
const increment = () => setCount(count + 1);
return (
<>
<div>{count}</div>
<button onClick={decrement}>-</button>
<button onClick={increment}>+</button>
</>
);
};
export default Counter;
코드만 보고는 코드가 제대로 동작하는지 확인하기 어렵기 때문에 우리는 test 코드를 이용해 확인해보고자 한다.
// Counter.test.js
import { render } from '@testing-library/react';
import Counter from './Counter';
describe('Counter test', () => {
it('should render Counter', () => {
render(<Counter />);
});
});
제 react 과제 코드에 적용해보고 싶었는데...... 라이트/다크모드 구현이 아직인 관계로 많은 페이지에 필요한 404 Not found 페이지를 정적 컴포넌트 테스팅하는 코드가 있어 예제로 가져와봤습니다!
// NotFound.js
function NotFound({ path }) {
return (
<>
<h2>Page Not Found</h2>
<p>해당 페이지({path})를 찾을 수 없습니다.</p>
<img
alt="404"
src="https://media.giphy.com/media/14uQ3cOFteDaU/giphy.gif"
/>
</>
);
}
위 코드가 렌더링되고 있는지 검증하는 테스트 코드를 작성해보자.
import { render, screen } from "@testing-library/react";
import { NotFound } from "./NotFound";
describe("<NotFound />", () => {
it("renders header", () => {
render(<NotFound path="/abc" />);
const heading = screen.getByRole("heading", {
name: "Page Not Found",
});
expect(heading).toBeInTheDocument();
});
});
- 테스트 파일에 React를 임포트하고,
@testing-library/react모듈로 부터render함수와screen객체를 불러온다.- 테스트 대상인
<NotFound />컴포넌트를 import 해온다.render()함수로<NotFound />컴포넌트를 HTML 문서에 렌더링한다.screen객체의 getByRole() 함수로 "Page Not Found"라는 텍스트를 담고 있는<h2/>요소를 얻는다.- 마지막으로
jest-dom의toBeInTheDocument()matcher 함수를 이용해서 해당<h2/>요소가 HTML 문서 상에 존재하는 검증한다.
동일한 방식으로 본문이 제대로 렌더링되고 있는지도 검증해볼 수 있다.
it("renders paragraph", () => {
render(<NotFound path="/abc" />);
const paragraph = screen.getByText(/^해당 페이지/);
expect(paragraph).toHaveTextContent("해당 페이지(/abc)를 찾을 수 없습니다.");
});
getByText() 쿼리 함수는 문자열 뿐만 아니라 정규식도 인자로 받을 수 있다. jest-dom의 toHaveTextContent() matcher 함수를 이용해서 <p/> 엘리먼트 속의 텍스트가 예상과 일치하는지 검증한다.
it("renders image", () => {
render(<NotFound path="/abc" />);
const image = screen.getByRole("img", { name: /404/i });
// const image = screen.getByAltText("404");
expect(image).toHaveAttribute(
"src",
"https://media.giphy.com/media/14uQ3cOFteDaU/giphy.gif"
);
});
이미지 같은 경우, <img/> 태그는 내부에 텍스트가 없기 때문에, 역할(role)로 선택하는 getByRole() 함수나 alt 속성값으로 선택하는 getAltText() 함수를 사용한다. jest-dom의 toHaveAttribute() matcher 함수를 이용해서 <img/> 엘리먼트의 src 속성값이 정확한지 검증합니다.
위에서 볼 수 있듯이 Testing Library는 getByXxx() 외에도 queryByXxx()와 findByXxx() 등 매우 다양한 종류의 쿼리 함수를 제공하고 있다.
RTL의 동작과정이 초반에 쓰여있어 이해에 도움이 되는것 같아요! 예시를 들어서 설명해주셔서 이해에 도움이 많이 되는것 같습니다. 예시에 쓰인 문법들도 잘 설명해주셔서 너무 좋아요! 좋은 아티클 써주셔서 감사하고 수고하셨습니다~~!!!
우선 이세계스터디 커버사진이 굉장히 인상적이네요!! 굉장히 귀얍습니다ㅎㅎ
리액트 컴포넌트를 테스트할 다른 도구들이 존재한다는 것은 몰랐네요! 또 RTL이 가상의 윈도우 객체를 제공해서 조작이 가능한 것 처럼 보이게 하는 원리도 신기하네용 설치 방법도 yarn 과 npm 모두 예시 들어주신거 센스쟁이 귀요미 우주최강 신지입니다. 예시로 직접 실습해본 부분도 정성이 느껴지고 이해가 쏙쏙 됩니다 정성스럽고 신지같이 귀여운 아티클 감사합니다! 이번 리액트 스터디를 하면서 신지의 아티클을 보면서 많이 배우고 갑니다 ! 앱잼 파이팅~~
아티클을 읽다가 E2E 테스트의 개념이 생소해서 한 번 알아보게 됐어요 End To End 테스트의 약자로 애플리케이션의 흐름을 처음부터 끝까지 테스트하는 걸 의미한다고 하네요 !
카카오 기술 블로그에도 관련 글이 있네요 함 둘러보고 오시면 좋을 것 같아요 ~!
예제 코드들을 통해 테스트 코드에 대해 이해해볼 수 있어서 좋았습니다 또한 단계별로 설명해주셔서 어떤식으로 코드가 진행되는지 알 수 있었어요. 유익한 아티클 감사합니다 고생하셨어요!
RTL(React Testing Library)에 대해 많은 것을 배울 수 있어 정말 유익 했어요!기존의 테스팅 도구들은 코드 내부를 해킹하는 느낌이 강했는데, RTL은 실제 사용자 경험을 반영하여 테스트를 수행할 수 있게 해준다는 점이 인상깊었습니다!또한, 가상의 window 객체를 제공함으로써 브라우저 환경이 아니더라도 DOM 조작이 가능하다는 사실을 새롭게 알게 되었어요.NotFound 컴포넌트를 테스트하는 과정에서 getByRole, getByText, getByAltText 등 다양한 쿼리 함수를 사용하는 방법을 명확하게 설명해줘서 이해하기 쉬웠습니다!! 좋은 아티클 감사합니다!
글 진~~짜 깔끔하네요!
RTL에 대한 개념 설명 및 예시 코드를 통한 동작 방식 설명까지 세세하게 설명해주신 덕분에 이해가 잘 되었습니다 ㅎㅎ
좋은 글 감사합니다!
리액트 과제 화이팅~~~!!!