RTL(React Testing Library)은 React 테스팅을 위해 React App에 내장되어 있는 시스템이다. RTL에는 Jest가 포함되어 있어 이를 통해 기능 테스트를 진행할 수 있다.
Jest 컴포넌트 테스트
지난 Jest 포스팅에 이어서 Jest를 사용하여 React 프로젝트를 테스트해 보기로 했다.
먼저 create react-app
으로 테스트를 진행할 React 프로젝트를 생성했다.
yarn create react-app jest-tutorial
React는 기본 테스트 도구로 Jest를 사용하기 때문에 별도 설치 없이 사용할 수 있고, src 디렉터리에 App.test.js가 존재하는 걸 확인할 수 있다. learn react 링크의 렌더링을 테스트하는 코드가 작성되어 있다.
import { render, screen } from "@testing-library/react"
import App from "./App"
test("renders learn react link", () => {
render(<App />)
const linkElement = screen.getByText(/learn react/i)
expect(linkElement).toBeInTheDocument()
})
yarn test
를 해보면 다음과 같이 결과가 출력된다.
$ yarn test
yarn run v1.22.18
$ react-scripts test
PASS src/App.test.js
✓ renders learn react link (16 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.785 s
Ran all test suites related to changed files.
다른 컴포넌트에서 테스트를 진행하기 위해 기존 테스트 코드를 삭제하고, Container 컴포넌트와 Container.test.js를 작성했다.
// App.js
import Container from "./Container"
const id = null
function App() {
return (
<div>
<Container id={id} />
</div>
)
}
export default App
// Container.js
// 삼항 연산자로 id 값이 있는 경우 id를 출력, 그렇지 않으면 h1 태그 출력
function Container({ id }) {
return id ? <h1>{id}</h1> : <h1>id가 발견되지 않습니다.</h1>
}
export default Container
// Container.test.js
import { render, screen } from "@testing-library/react"
import Container from "./Container"
const id = 123
// id 값이 있는지 검사하는 테스트
test("id 값 테스트", () => {
const el = <Container id={id} />
expect(el).toMatchSnapshot()
})
# 검사 성공
PASS src/Container.test.js
✓ id 값 테스트 (1 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 1 passed, 1 total
Time: 0.229 s, estimated 1 s
Ran all test suites.
SnapShot
여러 가지 테스트를 추가할 수 있는데, id 값 확인과 함께 id가 123이 맞는지 확인하는 테스트도 해볼 수 있다.
import { render, screen } from "@testing-library/react"
import Container from "./Container"
const id = 123
test("id 값 테스트", () => {
const el = <Container id={id} />
expect(el).toMatchSnapshot()
})
test("id가 123인지 검사", () => {
render(<Container id={id} />)
const containerElement = screen.getByText(/123/i)
expect(containerElement).toBeInTheDocument()
})
# if id = 123
PASS src/Container.test.js
✓ id 값 테스트 (2 ms)
✓ id가 123인지 검사 (12 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 1 passed, 1 total
Time: 0.263 s, estimated 1 s
Ran all test suites related to changed files.
# if id = 200
FAIL src/Container.test.js
✕ id 값 테스트 (3 ms)
✕ id가 123인지 검사 (13 ms)
● id 값 테스트
expect(received).toMatchSnapshot()
Snapshot name: `id 값 테스트 1`
- Snapshot - 1
+ Received + 1
<Container
- id={123}
+ id={200}
/>
6 | test("id 값 테스트", () => {
7 | const el = <Container id={id} />;
> 8 | expect(el).toMatchSnapshot();
| ^
9 | });
10 |
11 | test("id가 123인지 검사", () => {
at Object.<anonymous> (src/Container.test.js:8:14)
● id가 123인지 검사
TestingLibraryElementError: Unable to find an element with the text: /123/i. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
Ignored nodes: comments, script, style
<body>
<div>
<h1>
200
</h1>
</div>
</body>
11 | test("id가 123인지 검사", () => {
12 | render(<Container id={id} />);
> 13 | const containerElement = screen.getByText(/123/i);
| ^
14 | expect(containerElement).toBeInTheDocument();
15 | });
16 |
at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:40:19)
at Object.<anonymous> (src/Container.test.js:13:35)
› 1 snapshot failed.
Snapshot Summary
› 1 snapshot failed from 1 test suite. Inspect your code changes or press `u` to update them.
Test Suites: 1 failed, 1 total
Tests: 2 failed, 2 total
Snapshots: 1 failed, 1 total
Time: 0.47 s, estimated 1 s
Ran all test suites related to changed files.
두 번째 테스트에서 id 값 테스트가 값 200이 입력되었음에도 실패하게 되는 이유는 첫 번째 테스트에서 Snapshot이 123으로 입력되었기 때문이다. src 디렉터리에 snapshots가 생성되어 있는 것을 볼 수 있는데, 이 곳에 스냅샷이 업데이트 되어 있다.
// Container.test.js.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`id 값 테스트 1`] = `
<Container
id={123}
/>
`;
id 값이 123으로 기록되었기 때문에 이외에 다른 id 값이 입력되면 실패했음을 알린 것이다.
› 1 snapshot failed from 1 test suite. Inspect your code changes or press `u` to update them.
따라서 새로 입력한 값을 스냅샷에 업데이트 하고 싶으면 u 키를 눌러 반영하거나, 계속 테스트를 진행하게끔 선택할 수 있다.
사용자의 판단에 따라 스냅샷을 업데이트하며 테스트를 진행하면 될 것 같다.