230530(ํ)
๐ ์ฑ์ฅ์ผ์ง 4.0
์ฑ
ํ๋ณตํ ์ด๊ธฐ์ฃผ์์(์จ์ธ ๋ค์ด์ด)
์ ๋ด์ฉ์ ์๊ทน๋ฐ์ ์์ํ๋ ์๋ฐํ ์ฑ์ฅ๊ธฐ๋ก
์ด์์๋ ๊ฝ๊ณผ ์ฃฝ์ ๊ฝ์ ์ด๋ป๊ฒ ๊ตฌ๋ณํ๋๊ฐ?
์ฑ์ฅํ๊ณ ์๋ ๊ฒ์ด ์ด์ ์๋ ๊ฒ์ด๋ค.
์๋ช ์ ์ ์ผํ ์ฆ๊ฑฐ๋ ์ฑ์ฅ์ด๋ค!
๐ณ (1.0)ํค์๋
์ต๋ํ ๊ฐ๋จํ๊ฒ ์ ๋ฆฌ, ์ถํ์ ๋ณด๋ฉด์ ์ค์ค๋ก ์ค๋ช
๐ (2.0)๊ฒฝํ ์์ฃผ๋ก
๋จ์ ์ ๋ณด๋ฅผ ์ ๋ฌํ๊ธฐ๋ณด๋ค ๋ฌด์์ ๋ฐฐ์ ๊ณ ์ด๋ป๊ฒ ํด๊ฒฐํ๋์ง ์งง๊ณ ๊ฐ๋จํ๊ฒ ์์ฑ
โ๏ธ (3.0)์ ํด์ง ํ ํ๋ฆฟ์ ๋ง์ถฐ์
ํค์๋, ๊ฒฝํ ๋ชจ๋ ์ข๋ค. ๋ค๋ง ๋งค์ผ ์์ฑํ๊ธฐ๋ก ๋ง์ ๋จน์๋งํผ ํต์ฌ๋ง ๊ฐ๊ฒฐํ๊ฒ ์ ๋ฆฌํ ์ ์๊ฒ ํ ํ๋ฆฟ์ ์์ฑ
(3.1)230102๋ถํฐ ์์๋๋ ํ์ต์ ๊ดํ ๋ด์ฉ ์ถ๊ฐ
(3.2)230313๋ถํฐ ์ข๋ ๊ฒฝํ, ๊ฐ์ ์์ฃผ์ ๋ด์ฉ๋ ๋ด๊ธฐ!
๐พ (4.0)ํ์ต ํค์๋์์ ์ต๋ํ ๊ฐ๋จํ ์ ๋ณด ์ ๊ณต, ๊ณ ๋ฏผ์์ ๋ด ๊ฒฝํ์ ์์ธํ ์ ์!
๐ ์ค๋์ ํ์ต ํค์๋
ํ ์คํธ ์ฝ๋
ํ ์คํธ ์ฝ๋๋ ์ ์์ฑํ ๊น?
- ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๊ฐ๋ฐ์๋ ์ฝ๋๋ฅผ ๋์ฑ ์์ ํ๊ฒ ๋ฆฌํฉํ ๋งํ ์ ์๋ค.
- ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๊ฐ๋ฐ์๋ ๋์ค์ ์ฝ๋๋ฅผ ๋์ฑ ์์ฝ๊ฒ ์ ์ง๋ณด์ํ ์ ์๋ค.
- ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๊ฐ๋ฐ์๋ ๋์ค์ ๋ค๋ฅธ ์ฌ๋์ด ๋ง๋ ์ฝ๋๋ฅผ ๋์ฑ ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋ค.
์์ 3๊ฐ์ง ์ด์ ๊ฐ ๊ฐ์ฅ ๋ํ์ ์ธ ์ด์ ์ธ ๊ฒ ๊ฐ๋ค. ์ค์ ํ์ ์์๋ ์๊ฐ ๊ด๊ณ ์ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ์ง ๋ชปํ์ง๋ง, ํ ์คํธ ๊ธฐ๋ฐ์ ๊ฐ๋ฐ(TDD)์ ๋์ ํ๊ณ ์ถ์ดํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค๊ณ ํ๋ค.(์ฅ๊ธฐ์ ์ผ๋ก ๋ดค์ ๋๋, ํจ์ฌ ๋ ๋์ด ๋ ํ ๋..!)
์ฌ์ค ๊ทธ๋์ Jest
๋ฅผ ํตํ ๊ฐ๋จํ ๋จ์ ํ
์คํธ๋ ์งํํด๋ณด์๋ค.(์ฃผ๋ก util ํจ์๋ค) ๊ทธ๋ ๋ค๋ฉด ๋ฆฌ์กํธ๋ ์ด๋ป๊ฒ ํ
์คํธ ์ฝ๋๋ฅผ ์์ฑํ ๊น?
๋ฆฌ์กํธ ํ ์คํธ ์ฝ๋
์ค๋์ ๋ฆฌ์กํธ ํ ์คํธ ์ฝ๋์ ๋ํด์ ํ์ตํ๋ค. ๋ฆฌ์กํธ๋ ์ฃผ๋ก ์ปดํฌ๋ํธ ๋จ์(์๋ฐํ๋ ํจ์ ๋จ์)์ ๋ํ ์ ๋ ํ ์คํธ๋ฅผ ์งํํ๋ค.
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();
});
test('welcom message2 by queryByText', () => {
const {getByText, queryByText} = render( <App />);
expect(queryByText(/welcome/i)).toBeInTheDocument();
});
๋ํ, ์ด๋ค ํ๊ทธ์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์์ผ์ ๋ฒ์ด์ง๋ ์ผ์ ๋ํ ์ธ๋ถ์ ์ธ ํ ์คํธ๋ ์งํํ ์ ์๋ค.
import {render, screen, fireEvent} from '@testing-library/react'
it('App.js: button์ clickํ๋ฉด ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ๋
ธ์ถ๋๋ค', () => {
const {getByText} = render( <App />);
fireEvent.click(getByText('loading data'))
getByText('newdata');
})
๊ทธ๋ ๋ค๋ฉด ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ณ ์ด์ ๋ํ ํ ์คํธํ ํ๊ณ ์ถ์ ๋ ์ด๋ป๊ฒ ํด์ผํ ๊น?
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
it('App.js: button์ clickํ๋ฉด 1๋ฒ API ์๋ต ๋ฐ์ดํฐ๊ฐ ๋
ธ์ถ๋๋ค', async () => {
//given
// 'https://jsonplaceholder.typicode.com/todos/1' ์์ฒญ ํ ์๋ต ๋ฐ์ดํฐ์ title ๊ฐ์ด๋ค.
const title = "delectus aut autem";
//when
const {getByText} = render( <App />);
fireEvent.click(getByText('loading data'))
//then
await waitFor(() => getByText(title));
})
์ข๋ ์์ธํ ํ ์คํธ ์ฝ๋ ๋ด์ฉ์ ์ถํ ๋ ๋ฐฐ์๋ณด๋ ค ํ๋ค.(๋ค์ ํ๋ก์ ํธ๋ TDD๋ก ํด๋ณด๊ธฐ!)
๐ ์์ฝ ๋ฐ ํ๋ฃจ ๊ฐ๋จ ํ๊ณ
์ต๊ทผ ์ฌ๋ผํ ๋๋ฌธ์ ๊ฐ๋ฐ ์์์ด ์กฐ๊ธ ๋ฎ์์ก์๋๋ฐโฆ! ์ค๋ ๋ค์ ํํ ์๊ฒผ๋ค!!! ๋๋ ์ด ์ผ์ด๋ ์ ๋ง๋ ํธ์ธ๊ฐ๋ณด๋ค!
์ค๋์ ์ํ ์
- ์ค๋ ์ด์ฌํ ๋ชฉํํ๋งํผ ๊ตฌํํด๋ธ ์
์ค๋์ ์์ฌ์ด ์
- ์์!
์ฐธ๊ณ
- ์ฝ๋์ค์ฟผ๋ ํ์ต ๋ด์ฉ
- ๋ฆฌ์กํธ ํ ์คํธ ์ฝ๋ ์์ฑํ๊ธฐ