September 22, 2022
์ํํธ์จ์ด ํ ์คํธ(Software Testing)์ ์ํํธ์จ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ ์ ํ์ด ์๋๋ ๋๋ก ์๋ํ๋์ง ํ๊ฐํ๊ณ ํ์ธํ๋ ๊ณผ์ ์ ๋๋ค. ํ ์คํ ์ ํตํด ๋ฒ๊ทธ ๋ฐฉ์ง, ๊ฐ๋ฐ ๋น์ฉ ์ ๊ฐ, ์ฑ๋ฅ ํฅ์ ๋ฑ์ ์ฅ์ ์ ์ป์ ์ ์์ต๋๋ค.
์ํํธ์จ์ด ๊ฐ๋ฐ์๋ก์ ์ต์ข ์ฌ์ฉ์๋ฅผ ์ผ๋์ ๋๊ณ ํ ์คํธ๋ฅผ ์คํํ๊ณ , ์ฌ์ฉ์๊ฐ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ์คํธ ํจ์ผ๋ก์จ ํ๋ก๊ทธ๋จ์ด ์คํจํ ๊ฐ๋ฅ์ฑ์ ๋ฎ์ถ๋ ๊ฒ์ ์ค์ํฉ๋๋ค.
์๋ํ๋ ํ ์คํ ์ ์ฌ์ ์ ์ค๋น๋ ํ ์คํธ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ ์ฅ์น์ ์ํด ์ํ๋ฉ๋๋ค. ์ด๋ฌํ ํ ์คํธ๋ ํด๋์ค์ ๋จ์ผ ๋ฉ์๋๋ฅผ ๊ฒ์ฌํ๋ ๊ฒ๋ถํฐ ์ผ๋ จ์ ๋ณต์กํ UI ์์ ์ํ์ ์์ด ๋์ผํ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋์ง ๊ฒ์ฆํ๋ ๊ฒ๊น์ง ๋ณต์ก์ฑ์ด ํจ์ฌ ๋ค์ํ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์๋ ํ ์คํธ๋ณด๋ค ๋ ๊ฐ๋ ฅํ๊ณ ์ ๋ขฐํ ์ ์์ต๋๋ค.
๋จ์ ํ ์คํธ๋ ๋งค์ฐ ๊ธฐ๋ณธ์ ์ด๋ฉฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ค ์ฝ๋์์ ์ํ๋ฉ๋๋ค. ์ด๋ฌํ ํ ์คํธ๋ ์ํํธ์จ์ด์ ๋ฉ์๋์ ํจ์์์ ์ฌ์ฉํ๋ ๊ฐ ํด๋์ค, ์ปดํฌ๋ํธ ๋๋ ๋ชจ๋์ ํ ์คํธํ๋ ์์ ์ด ์๋ฐ๋ฉ๋๋ค. ์ง์์ ํตํฉ ์๋ฒ๋ ๋น๊ต์ ์ ๋ ดํ ๋น์ฉ์ผ๋ก ๋งค์ฐ ๋น ๋ฅด๊ฒ ๋จ์ ํ ์คํธ๋ฅผ ์ํํ ์ ์์ต๋๋ค.
ํตํฉ ํ ์คํธ๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ํ ์ปดํฌ๋ํธ๋ ์๋น์ค๊ฐ ์ ๋๋ก ์๋ํ๋์ง ํ์ธํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ ์์ฉ์ ํ ์คํธํ๊ฑฐ๋ ๋ง์ดํฌ๋ก ์๋น์ค๊ฐ ์๋ํ ๋๋ก ์ํธ ์์ฉํ๋๋ก ์ ๊ณตํ๋ ๊ฒ์ ํฌํจํ ์ ์์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฌ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ค์ด ์๋ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ํ ์คํธ๋ฅผ ์ํํ๋ ๋ฐ ์ถ๊ฐ์ ์ธ ๋น์ฉ์ด ๋ฐ์ํฉ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ ๋น์ฆ๋์ค ์๊ตฌ ์ฌํญ์ ๊ธฐ๋ฅ ํ ์คํธ์ ์ฃผ์ ์ด์ ์ ๋๋ค. ๊ธฐ๋ฅ ํ ์คํธ์์๋ ์ํ๋๋ ๋์ ์์คํ ์ ์ค๊ฐ ์ํ๋ฅผ ์ฒดํฌํ์ง ์๊ณ ์ํ์ ๊ฒฐ๊ณผ๋ง ํ์ธํฉ๋๋ค.
๋ ๋ค ์ํธ ์์ฉํ๊ธฐ ์ํด ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ ํตํฉ ํ ์คํธ์ ๊ธฐ๋ฅ ํ ์คํธ๋ ์ข ์ข ํผ๋๋๊ณค ํฉ๋๋ค. ๊ธฐ๋ฅ ํ ์คํธ์์๋ ์ ํ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํน์ ๊ฐ์ ์ป์ ๊ฒ์ผ๋ก ์์ํ์ง๋ง, ํตํฉ ํ ์คํธ๋ ์ฌ์ฉ์๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฟผ๋ฆฌํ ์ ์๋์ง๋ง ํ์ธํฉ๋๋ค.
์ข ๋จ ๊ฐ ํ ์คํธ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฒด ๋งฅ๋ฝ์์ ์ํํธ์จ์ด๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์ ํ๋์ ์๋ฎฌ๋ ์ด์ ํฉ๋๋ค. ์น ํ์ด์ง๋ฅผ ๋ก๋ํ๊ฑฐ๋ ๋ก๊ทธ์ธํ๋ ๊ฒ์ฒ๋ผ ๊ฐ๋จํ ์๋๋ฆฌ์ค๋ ์ด๋ฉ์ผ ์๋ฆผ, ์จ๋ผ์ธ ๊ฒฐ์ ์ฒ๋ผ ๋ค์ ๋ณต์กํ ์๋๋ฆฌ์ค์ ๋ํด์ ๋ค์ํ ์ฌ์ฉ์ ํ๋ฆ์ด ์๋ํ ๋๋ก ์๋ํ๋์ง ํ์ธํฉ๋๋ค.
์ข ๋จ ๊ฐ ํ ์คํธ๋ ๋งค์ฐ ์ ์ฉํ์ง๋ง ์คํํ๋ ๋ฐ ๋น์ฉ์ด ๋ง์ด ๋ค๊ณ , ์๋ํ๋ ๊ฒฝ์ฐ์๋ ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ ๋น ๋ฅด๊ฒ ๋ฐ๊ฒฌํ๋ ค๋ฉด, ์ ํ๋ ์์ ์ค์ํ ์ข ๋จ ๊ฐ ํ ์คํธ๋ฅผ ๊ฐ๊ณ ํ์ ์์ค์ ํ ์คํธ(๋จ์ ๋ฐ ํตํฉ ํ ์คํธ)์ ๋ ์์กดํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ธ์ ํ ์คํธ๋ ์์คํ ์ด ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ ์ถฉ์กฑํ๋์ง ์ฌ๋ถ๋ฅผ ๊ณต์์ ์ผ๋ก ๊ฒฐ์ ํ๋ ํ ์คํธ์ ๋๋ค. ํ ์คํธ ๋์ ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ๋ฉด์ ์ฌ์ฉ์ ๋์์ ์ฌํํ๋ ๋ฐ ์ง์คํฉ๋๋ค. ํ ๋จ๊ณ ๋ ๋์๊ฐ ์์คํ ์ ํจ์จ์ฑ์ ํ๊ฐํ๊ณ ํน์ ํ ๋ชฉํ๊ฐ ๋ฌ์ฑ๋์ง ์์ผ๋ฉด ๊ฐ์ ์ ๊ฑฐ๋ถํ ์ ์์ต๋๋ค.
์ฑ๋ฅ ํ ์คํธ๋ ํน์ ์ํฌ๋ก๋๋ฅผ ์ฒ๋ฆฌํ๋ ์์คํ ์ ๋ฅ๋ ฅ์ ํ๊ฐํฉ๋๋ค. ์ด๋ฌํ ํ๊ฐ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ขฐ์ฑ, ์๋, ํ์ฅ์ฑ ๋ฐ ์๋ต์ฑ์ ๊ฒฐ์ ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฑ๋ฅ ํ ์คํธ๋ ๋ง์ ์์ ์์ฒญ์ด ์ฒ๋ฆฌ๋ ๋ ์๋ต ์๊ฐ์ ๋ชจ๋ํฐ๋งํ๊ฑฐ๋ ์์คํ ์ด ์๋นํ ์์ ๋ฐ์ดํฐ์ ์ด๋ป๊ฒ ์๋ตํ๋์ง ํ๊ฐํ ์ ์์ต๋๋ค. ํ๋ก๊ทธ๋จ์ด ์ฑ๋ฅ ํ์ค์ ์ถฉ์กฑํ๋์ง ํ๊ฐํ๊ณ , ๋ณ๋ชฉ ํ์์ ์ฐพ๊ณ , ํธ๋ํฝ์ด ๋ง์ ๋ ์์ ์ฑ์ ์ธก์ ํ๊ณ , ํจ์ฌ ๋ ๋ง์ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
์ค๋ชจํฌ ํ ์คํธ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ธฐ๋ณธ ์๋์ ๊ฒ์ฌํ๋ ๊ฐ๋จํ ํ ์คํธ์ ๋๋ค. ์ด ํ ์คํธ๋ ์ ์ํ๊ฒ ์ํ๋๋๋ก ์ค๊ณ๋์์ผ๋ฉฐ, ์ฃผ์ ์์คํ ์ปดํฌ๋ํธ๊ฐ ๊ณํ๋๋ก ์๋ํ๊ณ ์๋ค๋ ํ์ ์ ์ ๊ณตํ๋ ๊ฒ์ ๋ชฉ์ ์ด ์์ต๋๋ค.
์ค๋ชจํฌ ํ ์คํธ๋ ๋ ๋น์ฉ์ด ๋ง์ด ๋๋ ํ ์คํธ๋ฅผ ์คํํ ์ ์๋์ง๋ฅผ ๊ฒฐ์ ํ๊ธฐ ์ํด ์ ๋น๋๋ฅผ ๋ง๋ ์งํ์, ๋๋ ์๋ก ๋ฐฐํฌ๋ ํ๊ฒฝ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ ๋๋ก ์๋ํ๋์ง ํ์ธํ๊ธฐ ์ํด ๋ฐฐํฌ ์งํ์ ๋์์ด ๋ ์ ์์ต๋๋ค.
ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ์์๋ ํ ์คํธ ์ผ์ด์ค๋ฅผ ๊ฒ์ฆํ๋ ์ฝ๋๋ณด๋ค ํ ์คํธ ์ผ์ด์ค๋ฅผ ๋จผ์ ์์ฑํด์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ์ ๋น ๋ฅธ ๊ฐ๋ฐ ์ฃผ๊ธฐ๋ฅผ ๋ฐ๋ณตํ๋ ๋ฐ ์์กดํฉ๋๋ค. ์๋ํ๋ ๋จ์ ํ ์คํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ค๊ณ ๋ฐ ์ข ์์ฑ์ ๋ฌด์ ํ ๋ถ๋ฆฌ๋ฅผ ์ง์ํฉ๋๋ค.
ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ์ ๋ชจํ ๋ ์๋์ ๊ฐ์ต๋๋ค.
ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ์ ์ฌ์ฉํ ๋, ํจ์ ์์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ ์ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋จผ์ ํ์ ์คํฌ๋ฆฝํธ ๊ธฐ๋ฐ์ ๋ฆฌ์กํธ ์ฑ์ ๋ง๋ค์ด ๋ด ์๋ค.
npx create-react-app jest-example --template typescript
์ด์ package.json
์ ์ด๋ฉด jest-dom
๊ณผ testing-library/react
๊ฐ ์ด๋ฏธ ์ข
์์ฑ์ผ๋ก ์ค์น๋์ด ์์์ ์ ์ ์์ต๋๋ค.
jest-dom
: ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ jest๋ฅผ ํ์ฅํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ์ปค์คํ
jest ๋งค์ฒ(Matcher)๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ
์คํธ๊ฐ ๋ ์ ์ธ์ ์ด๊ณ , ๋ช
ํํ๊ฒ ์ฝ๊ณ ์ ์ง ๊ด๋ฆฌํ ์ ์์ต๋๋ค.testing-library/react
: ๋ธ๋ผ์ฐ์ ์์ React์ ์ํด ๋ ๋๋ง ๋ ์ค์ DOM ํธ๋ฆฌ๋ฅผ ํ
์คํธํ๊ธฐ ์ํด ๋ง๋ค์ด์ง ํ
์คํธ ์ ํธ๋ฆฌํฐ ๋๊ตฌ์
๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ชฉํ๋ ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ์ ์ฌํ ํ
์คํธ๋ฅผ ์์ฑํ๋๋ก ๋๋ ๊ฒ์
๋๋ค.src ๋๋ ํฐ๋ฆฌ์๋ ๋ชจ๋ ์ฑ ์ฝ๋์ App.test.tsx
๋ผ๋ ํ์ผ์ด ํฌํจ๋์ด ์์ต๋๋ค. ์ด ํ์ผ์๋ App ์ปดํฌ๋ํธ๊ฐ ๋งํฌ๋ฅผ ๋ ๋๋ง ํ๋์ง ํ์ธํ๋ ํ
์คํธ๊ฐ ํฌํจ๋์ด ์์ต๋๋ค. ์ด์ ํ
์คํธ ์ฝ๋๋ฅผ ๋ถ์ํ๊ณ ์ด๋ค ์ญํ ์ ํ๊ณ ์๋์ง ํ์ธํด๋ด
์๋ค.
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';
// ํ
์คํธ์ ๋ชฉ์ ์ ๊ฐ๋ตํ๊ฒ ์ค๋ช
ํฉ๋๋ค.
test('renders learn react link', () => {
// ์ค๋น(Arrange): ํ
์คํธ ํ๊ฒฝ๊ณผ ์ปดํฌ๋ํธ ๋ ๋๋ง์ ์ค๋นํฉ๋๋ค.
render(<App />);
// ์คํ(Act): ์์๋๋ ๋งํฌ๋ฅผ ์ฐพ์ต๋๋ค.
const linkElement = screen.getByText(/learn react/i);
// ๊ฒ์ฆ(Assert): ๋ฌธ์์ ํ์ํ ๋งํฌ๊ฐ ์๋์ง ํ์ธํฉ๋๋ค.
expect(linkElement).toBeInTheDocument();
});
์ด์ ๋ค์ ๋ช ๋ น์ ์คํํ์ฌ ํ ์คํธ๋ฅผ ์คํํฉ๋๋ค.
npm run test
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด์ App.tsx
์ ๋ณ๊ฒฝํ๊ณ ํ
์คํธ ๊ฒฐ๊ณผ๋ฅผ ์คํจ์ํต๋๋ค. App.tsx
ํ์ผ๋ก ์ด๋ํ์ฌ, โLearn Reactโ๋ฅผ โLetโs Learnโ์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค. ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
ํ ์คํธ๊ฐ ๊นจ์ง๋ ์ด์ ๋ DOM์ โlearn reactโ ๋ฌธ์์ด์ ํฌํจํ๋ ์์๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. โlearn reactโ ํ ์คํธ๊ฐ ํฌํจ๋ ์๋ก์ด ์๋ฆฌ๋จผํธ๋ฅผ ์ถ๊ฐํ๋ฉด ํ ์คํธ๋ ๋ค์ ์ฑ๊ณตํฉ๋๋ค.
์ด์ App.tsx
๋ก ์ด๋ํ์ฌ ์ ๊ธฐ๋ฅ์ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
export function add(a: number, b: number): number {
return a + b;
}
์ด์ App.test.tsx
๋ก ์ด๋ํ์ฌ ์ ํ
์คํธ๋ฅผ ์์ฑํด๋ณด๊ฒ ์ต๋๋ค.
describe('add function', () => {
describe('when given to integers', () => {
it('should return a add result', () => {
// ์ค๋น(Arrange): ์์๋๋ ๋ง์
๊ฒฐ๊ณผ์ ํจ์ ์ธ์๋ฅผ ์ค๋นํฉ๋๋ค.
// ์ด ์์์์๋ 5 + 8์ด 13์ด ๋๋ค๋ ๊ฒฐ๊ณผ๋ฅผ ์์ธกํฉ๋๋ค.
const [a, b, expected] = [5, 8, 13];
// ์ฌ๊ธฐ์๋, ๋ฐฐ์ด ๋น๊ตฌ์กฐํ๋ฅผ ํ์ฉํ์ฌ "a === 5," "b === 8," ๊ณผ "expected === 13"๊ณผ ๊ฐ์ด ํ ๋นํฉ๋๋ค.
// ์คํ(Act): ์ฐธ์ธ ํจ์ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ์ํด add ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
const result = add(a, b);
// ๊ฒ์ฆ(Assert): ์ด์ ํจ์์ ์ถ๋ ฅ๊ณผ ์์ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ตํฉ๋๋ค.
expect(result).toEqual(expected);
});
});
});
์ด์ ํ ์คํธ๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ํ์๋ฉ๋๋ค.
์ด์ ๋ช ๊ฐ์ง ์ปดํฌ๋ํธ๋ฅผ ํ
์คํธํ ์๊ฐ์
๋๋ค. App.tsx
์์ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ๋ง๋ค์ด ๋ด
์๋ค.
export function Login() {
return (
<div>
<div>
<input type="email" name="email" placeholder="email" />
</div>
<div>
<input type="password" name="password" placeholder="password" />
</div>
<div>
<button type="button">Sign In</button>
<button type="button">Sign Up</button>
</div>
</div>
);
}
์ด์ App.test.tsx
๋ก ์ด๋ํ์ฌ ์ด ์ปดํฌ๋ํธ์ ๋ํ ํ
์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํฉ๋๋ค.
describe('Login component tests', () => {
let container: HTMLDivElement;
// beforeEach: ์ด ํ์ผ์ ๊ฐ ํ
์คํธ๊ฐ ์คํ๋๊ธฐ ์ ์ ์ด ํจ์๋ฅผ ์คํํฉ๋๋ค. ํจ์๊ฐ promise๋ฅผ ๋ฐํํ๊ฑฐ๋ ์์ฑ์์ธ ๊ฒฝ์ฐ, jest๋ ํ
์คํธ๋ฅผ ์คํํ๊ธฐ ์ ์ ํด๋น promise๊ฐ ํด๊ฒฐ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
ReactDOM.render(<Login />, container);
});
// ํ
์คํธ๊ฐ ์๋ก ๋ฐฉํด๋์ง ์๋๋ก ๋ง์ง๋ง์ ๋ชจ๋ ๊ฒ์ ์ด๊ธฐํํฉ๋๋ค.
afterEach(() => {
document.body.removeChild(container);
container.remove();
});
// ๊ฐ ์
๋ ฅ ํ๋๋ฅผ ๋ ๋๋งํ๊ธฐ ์ํ ํ
์คํธ๋ฅผ ์คํํฉ๋๋ค.
it('Renders all input fields correctly', () => {
// ์
๋ ฅ ํ๋๋ฅผ ์ ํํฉ๋๋ค.
const inputs = container.querySelectorAll('input');
// ์
๋ ฅ ํ๋๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋ ๋๋ง๋์๋์ง ํ์ธํฉ๋๋ค.
expect(inputs).toHaveLength(2);
// ์ฒซ ๋ฒ์งธ ์
๋ ฅ ํ๋ ๋ฐ ๋ ๋ฒ์งธ ์
๋ ฅ ํ๋๋ฅผ ๊ฐ๊ฐ "์ด๋ฉ์ผ" ๋ฐ "์ํธ"์ธ์ง ํ์ธํฉ๋๋ค.
expect(inputs[0].name).toBe('email');
expect(inputs[1].name).toBe('password');
});
// ๊ฐ ๋ฒํผ์ ๋ ๋๋งํ๊ธฐ ์ํ ํ
์คํธ๋ฅผ ์คํํฉ๋๋ค.
it('Renders all buttons correctly', () => {
const buttons = container.querySelectorAll('button');
expect(buttons).toHaveLength(2);
expect(buttons[0].type).toBe('button');
expect(buttons[1].type).toBe('button');
});
});
์์ฑ๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
import React from 'react';
import { render, screen } from '@testing-library/react';
import App, { add, Login } from './App';
import * as ReactDOM from 'react-dom';
// ํ
์คํธ์ ๋ชฉ์ ์ ๊ฐ๋ตํ๊ฒ ์ค๋ช
ํฉ๋๋ค.
test('renders learn react link', () => {
// ์ค๋น(Arrange): ํ
์คํธ ํ๊ฒฝ๊ณผ ์ปดํฌ๋ํธ ๋ ๋๋ง์ ์ค๋นํฉ๋๋ค.
render(<App />);
// ์คํ(Act): ์์๋๋ ๋งํฌ๋ฅผ ์ฐพ์ต๋๋ค.
const linkElement = screen.getByText(/learn react/i);
// ๊ฒ์ฆ(Assert): ๋ฌธ์์ ํ์ํ ๋งํฌ๊ฐ ์๋์ง ํ์ธํฉ๋๋ค.
expect(linkElement).toBeInTheDocument();
});
describe('add function', () => {
describe('when given to integers', () => {
it('should return a add result', () => {
// ์ค๋น(Arrange): ์์๋๋ ๋ง์
๊ฒฐ๊ณผ์ ํจ์ ์ธ์๋ฅผ ์ค๋นํฉ๋๋ค.
// ์ด ์์์์๋ 5 + 8์ด 13์ด ๋๋ค๋ ๊ฒฐ๊ณผ๋ฅผ ์์ธกํฉ๋๋ค.
const [a, b, expected] = [5, 8, 13];
// ์ฌ๊ธฐ์๋, ๋ฐฐ์ด ๋น๊ตฌ์กฐํ๋ฅผ ํ์ฉํ์ฌ "a === 5," "b === 8," ๊ณผ "expected === 13"๊ณผ ๊ฐ์ด ํ ๋นํฉ๋๋ค.
// ์คํ(Act): ์ฐธ์ธ ํจ์ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ์ํด add ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
const result = add(a, b);
// ๊ฒ์ฆ(Assert): ์ด์ ํจ์์ ์ถ๋ ฅ๊ณผ ์์ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ตํฉ๋๋ค.
expect(result).toEqual(expected);
});
});
});
describe('Login component tests', () => {
let container: HTMLDivElement;
// beforeEach: ์ด ํ์ผ์ ๊ฐ ํ
์คํธ๊ฐ ์คํ๋๊ธฐ ์ ์ ์ด ํจ์๋ฅผ ์คํํฉ๋๋ค. ํจ์๊ฐ promise๋ฅผ ๋ฐํํ๊ฑฐ๋ ์์ฑ์์ธ ๊ฒฝ์ฐ, jest๋ ํ
์คํธ๋ฅผ ์คํํ๊ธฐ ์ ์ ํด๋น promise๊ฐ ํด๊ฒฐ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
ReactDOM.render(<Login />, container);
});
// ํ
์คํธ๊ฐ ์๋ก ๋ฐฉํด๋์ง ์๋๋ก ๋ง์ง๋ง์ ๋ชจ๋ ๊ฒ์ ์ด๊ธฐํํฉ๋๋ค.
afterEach(() => {
document.body.removeChild(container);
container.remove();
});
// ๊ฐ ์
๋ ฅ ํ๋๋ฅผ ๋ ๋๋งํ๊ธฐ ์ํ ํ
์คํธ๋ฅผ ์คํํฉ๋๋ค.
it('Renders all input fields correctly', () => {
// ์
๋ ฅ ํ๋๋ฅผ ์ ํํฉ๋๋ค.
const inputs = container.querySelectorAll('input');
// ์
๋ ฅ ํ๋๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋ ๋๋ง๋์๋์ง ํ์ธํฉ๋๋ค.
expect(inputs).toHaveLength(2);
// ์ฒซ ๋ฒ์งธ ์
๋ ฅ ํ๋ ๋ฐ ๋ ๋ฒ์งธ ์
๋ ฅ ํ๋๋ฅผ ๊ฐ๊ฐ "์ด๋ฉ์ผ" ๋ฐ "์ํธ"์ธ์ง ํ์ธํฉ๋๋ค.
expect(inputs[0].name).toBe('email');
expect(inputs[1].name).toBe('password');
});
// ๊ฐ ๋ฒํผ์ ๋ ๋๋งํ๊ธฐ ์ํ ํ
์คํธ๋ฅผ ์คํํฉ๋๋ค.
it('Renders all buttons correctly', () => {
const buttons = container.querySelectorAll('button');
expect(buttons).toHaveLength(2);
expect(buttons[0].type).toBe('button');
expect(buttons[1].type).toBe('button');
});
});
์ด์ ๋ชจ๋ ํ ์คํธ๊ฐ ํต๊ณผ๋์์ผ๋ฏ๋ก, ๋ ๋ง์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ ๋จ์ ํ ์คํธ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
๋๊ท๋ชจ ์ฑ ์ผ์๋ก ํนํ ์ ์ง ๋ณด์ ๋ฐ ์ํํธ์จ์ด ์ง์ ๋น์ฉ์ ์ ๊ฐํ๊ธฐ ์ํด ์ ํ๋ฆฌ์ผ์ด์ ํ ์คํธ๋ ํ์์ ์ ๋๋ค. ์ด ๋ธ๋ก๊ทธ์์๋ Jest, React ๋ฐ Typescript๋ก ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ณผ ์ ์์ต๋๋ค. ๋ ๋ง์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ ๊ทธ ์ปดํฌ๋ํธ๋ค์ ์ํ ๋ ๋ง์ ํ ์คํธ๋ฅผ ์์ฑํ์ธ์. ์ ์ฒด ์์ค ์ฝ๋๋ Github์์ ์ฐพ์ ์ ์์ต๋๋ค.
๊ฐ์ฌํฉ๋๋ค.
๐ ํ๊ตญ์ด๋ก ๋ ํ๋ฐํธ์๋ ์ํฐํด์ ๋น ๋ฅด๊ฒ ๋ฐ์๋ณด๊ณ ์ถ๋ค๋ฉด Korean FE Article(https://kofearticle.substack.com/)์ ๊ตฌ๋ ํด์ฃผ์ธ์!