1. MSW ๋ฐฉ์์ mocking ์๋ฒ ๊ตฌํ
- feat.md ์ ๋ฐ๋ผ์ ๊ฐ๋ฐ์งํ.
- ๋์ ์ฒดํฌ~
- ์๋ฒ ์คํ
- service worker ๊ธฐ๋ฐ ์๋ต ํ์ธ

- ๊ตฌ์กฐ ์ดํด ๋ฐ MSW ํ์ต
์ฐธ๊ณ . Service Worker
- Service Worker ๋ฑ๋ก:
- ์์์ฝ๋, worker.start() ์คํ
- mockServiceWorker.js ํ์ผ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์ ๋ฑ๋ก
- ๋คํธ์ํฌ ๊ฐ๋ก์ฑ๊ธฐ
- ๋ชจ๋ fetch ์์ฒญ์ ๋คํธ์ํฌ๋ก ๋๊ฐ๊ธฐ ์ ์ ๊ฐ๋ก์ฑ.
- ๊ฐ๋ก์ฑ ์์ฒญ(URL, ๋ฉ์๋)์ handlers.js์ ์ ์๋ Mock ๋ชฉ๋ก๊ณผ ๋น๊ตํ์ฌ ์ผ์นํ๋ ํธ๋ค๋ฌ ์ฐพ๊ธฐ
- ์ผ์น์ : ์ค์ ์๋ฒ ํต์ ์์ด ํธ๋ค๋ฌ์ ์ ์๋ Mock ๋ฐ์ดํฐ(JSON)๋ฅผ ์ฆ์ ์์ฑ
- ๋ถ์ผ์น : ์์ฒญ์ bypassํ์ฌ ํต๊ณผ
- Service Worker๋ ์ด Mock ์๋ต์ ์น ํ์ด์ง์ fetch ํธ์ถ ์ง์ ์ผ๋ก ๋ฐํ

2. ๋จ์ํ ์คํธ์ ํตํฉํ ์คํธ
์ํํธ์จ์ด ํ ์คํธ ๋จ๊ณ

- ์ถ๊ฐ๋ก E2E ํ
์คํธ
- FE : ๋ธ๋ผ์ฐ์ ๋๋ headless ๋ธ๋ผ์ฐ์ ๊ธฐ๋ฐ ๋์ ํ ์คํธ
- BE: API ์์ฒญ๊ณผ ์๋ต ํ ์คํธ
2.1 ํ ์คํธ์ ๋์ ์ ์
- TodoAPP์ ์ด๋ป๊ฒ ํ ์คํธ ํ ๊น? ๋ญ ํ ์คํธ ํด์ผํ ๊น?
- TodoAPP ? TodoInput? TodoList? Hook?
2.2 ๋จ์ ํ ์คํธ์ ํตํฉํ ์คํธ
๋จ์ ํ ์คํธ (Unit Test)ํตํฉ ํ ์คํธ (Integration Test)
| ์ ์ | ๊ฐ๋ณ ์ปดํฌ๋ํธ/ํจ์๋ฅผ ๋ ๋ฆฝ์ ์ผ๋ก ํ ์คํธ | ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ํจ๊ป ๋์ํ๋์ง ํ ์คํธ |
| ๋ฒ์ | ํ๋์ ์ปดํฌ๋ํธ/ํจ์ | ์ฌ๋ฌ ์ปดํฌ๋ํธ + ์์กด์ฑ |
| ์คํ ์๋ | ๋น ๋ฆ (์ ms) | ์๋์ ์ผ๋ก ๋๋ฆผ |
| ๋ชฉ์ | ๊ฐ๋ณ ๋ก์ง์ ์ ํ์ฑ ๊ฒ์ฆ | ํตํฉ๋ ๋์ ๊ฒ์ฆ(์ ์ฒด ์์คํ ๋ ๋ฒจ๊น์ง) |
| ๋ชจํน | ์ธ๋ถ ์์กด์ฑ ๋ชจํน | ์ต์ํ์ ๋ชจํน (์ค์ ๋์ ์ ์ฌ) |
| ์คํจ ์ ์์ธ | ๋ช ํํจ (ํด๋น ์ปดํฌ๋ํธ) | ํ์ ํ์ (์ฌ๋ฌ ์์ ์ค ํ๋) |
| ์ ์ง๋ณด์ | ์ฌ์ | ์๋์ ์ผ๋ก ์ด๋ ค์ |
| ์ ๋ขฐ๋ | ๋ถ๋ถ์ ์ ๋ขฐ | ๋์ ์ ๋ขฐ (์ค์ ์ฌ์ฉ ํจํด) |
2.3 ๋จ์ ํ ์คํธ ์ค๊ณ ์์น
- ๋
๋ฆฝ์ฑ
- ๊ฐ ํ ์คํธ๋ ๋ค๋ฅธ ํ ์คํธ์ ์ํฅ์ ์ฃผ์ง ์์์ผํจ.
- mock ์ ํ์ฉํด์ ์ธ๋ถ ์์กด์ฑ ์ ๊ฑฐ
- ๋ช
ํ์ฑ
- ํ ์คํธ ์ด๋ฆ๋ง ๋ด๋ ๋ฌด์์ ๊ฒ์ฆํ๋์ง ์ ์ ์์ด์ผ ํจ
- ํ๋์ ํ ์คํธ๋ ํ๋์ ๋์๋ง ๊ฒ์ฆ
- ์์์ฑ(๋ฐ๋ณต๊ฐ๋ฅ์ฑ)
- ๊ฐ์ ์ ๋ ฅ์ ํญ์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
- ์ธ๋ถ ํ๊ฒฝ(์๊ฐ, ๋๋ค, ๋คํธ์ํฌ)์ ์์กดํ์ง ์์
- ๋น ๋ฅธ ์คํ
- ๊ฐ๋ฐ์๊ฐ ์ฝ๊ฒ ์์ฃผ ํ ์คํธ ํ ์ ์์ด์ผํจ.
2.4 ๋จ์ ์ปดํฌ๋ํธ ํ ์คํธ ์ ๋ต
ํ๋์ ์ปดํฌ๋ํธ -> ํ๋์ ๋จ์ ํ ์คํธ์ ๋น์ท
- ๋จ์ ํ
์คํธ๋ ์์กด์ฑ์ด ์๋ ๋
๋ฆฝ์ ์ธ ๋์์ด ์ ์
- TodoInput
- TodoList
- TodoInput ์์๋ ์ด๋คํ
์คํธ๋ฅผ ํด์ผํ ๊น?
- TodoInput ์ ์ญํ ์ ๋ฌด์์ธ๊ฐ?
- Props ๋ฅผ ๋ฐ์์ ๋์
- ์ฌ์ฉ์ ์ธํฐ๋์ ๊ฒ์ฆ
- ์ ๋ ฅ๊ฐ ๊ฒ์ฆ ๋ก์ง ํ์ธ
- ์ญํ ๊ธฐ๋ฐ์ผ๋ก ํ ์คํธ ์ฝ๋ ๊ตฌํ์ ๋ถํํ๋ค.
- ์ฝ๋ ์ดํดํ๊ธฐ.
- TodoInput ์ ์ญํ ์ ๋ฌด์์ธ๊ฐ?
- TodoList ์ ์ญํ ์?
- Props ๋ณ๊ฒฝ์ ๋ฐ๋ฅธ UI ๋ณํ
- ๋ฐ์ดํฐ ๋ ๋๋ง
- ์กฐ๊ฑด๋ถ ๋ ๋๋ง(๋ก๋ฉ์ด ์๋ค๋ฉด, ๋น๋ชฉ๋ก์ ?)
- useFetch
- API ํธ์ถ ์ ๋๋?
- ์ํ๊ด๋ฆฌ ํ์ธ
- fetch API ๋ชจํน ๋๋ MSW ์ฐ๋๋ฐฉ์
- TodoApp ํ
์คํธ ํด์ผํ๋?
- ํตํฉ ํ ์คํธ
- ์ ์ฒด ํ๋ก์ฐ ๋์ ํ์ธ
- ์ปดํฌ๋ํธ ๊ฐ ์ํธ์์ฉ ํ์ธ
3. Vitest์ React Testing Library
Vitest์ React Testing Library (RTL)๋ฅผ ์ฌ์ฉํด์ ๊ตฌํํ๋ ๊ฒ์ด ํ์ฌ์ ์ฃผ๋ฅ ์ค ํ๋
3.1. Vitest: (Test Runner)
Vitest๋ Vite ๊ธฐ๋ฐ์ ๋น ๋ฅด๊ณ ํจ์จ์ ์ธ ํ ์คํธ ๋ฌ๋๋ก, Jest์ API๋ฅผ ์๋ฒฝํ๊ฒ ์ง์ํ๋ค. Jest์ API์ ๋์ผํ๊ฒ ์ฌ์ฉํ์ฌ ํ ์คํธ ์คํ ํ๊ฒฝ๊ณผ ๊ฒ์ฆ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
(์์ ์๋ Mocha, QUnit, Karma ๋ฑ์ด ์์์)
๊ธฐ๋ฅ์ญํ ์์ ์ฝ๋
| ํ ์คํธ ์ ์ | ํ ์คํธ ์ผ์ด์ค์ ๊ทธ๋ฃน์ ์ ์ํ๋ค. | test('์ค๋ช ', () => {}) |
| ๊ฒ์ฆ (expect) | ํน์ ๊ฐ์ด ๊ธฐ๋ํ๋ ๊ฐ๊ณผ ์ผ์นํ๋์ง ํ์ธํ๋ค. | expect(value).toBe(1) |
| Mocking | ํจ์๋ ๋ชจ๋์ ์ค์ ๋์์ ๋์ฒดํ์ฌ ๊ฒฉ๋ฆฌํ๋ค. | const mockFn = vi.fn() |
| ๋น๋๊ธฐ ์ฒ๋ฆฌ | ๋น๋๊ธฐ ์ฝ๋๊ฐ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค. | test('...', async () => {}) |
3.2. React Testing Library (RTL)
RTL์ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๊ณ ์ฌ์ฉ์์ฒ๋ผ ์ํธ์์ฉํ๋ฉฐ DOM์ ๊ฒ์ํ๋ ์ ํธ๋ฆฌํฐ ์ธํธ๋ค.
RTL์ ๋ชฉํ: "์ฌ์ฉ์๊ฐ ์ค์ ๋ก ๋ณด๋ ๋ฐฉ์๋๋ก ํ ์คํธํ๋ผ"
๊ธฐ๋ฅ์ญํ ์์ ์ฝ๋
| ๋ ๋๋ง | ํ ์คํธ ํ๊ฒฝ์ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ค. | render() |
| DOM ์ฟผ๋ฆฌ | ์ฌ์ฉ์๊ฐ ๋ณด๋ ๋ฐฉ์์ผ๋ก ์์๋ฅผ ๊ฒ์ํ๋ค. | screen.getByRole('button') |
| ์ฌ์ฉ์ ์ด๋ฒคํธ | ์ค์ ์ฌ์ฉ์์ ํค๋ณด๋ ์ ๋ ฅ, ํด๋ฆญ ๋ฑ์ ์๋ฎฌ๋ ์ด์ ํ๋ค. | await userEvent.click(element) |
3.3. ์ค์น ๋ฐ ์ค์
- vitest, jsdom, c8 ๋ฑ์ ๋ชจ๋์ ์ค์นํ๊ณ
- vite.config.ts ํ์ผ์ ํ ์คํธ ํ๊ฒฝ(์: globals: true, environment: 'jsdom')์ ์ค์
3.4 ํ ์คํธ ๊ตฌ์กฐ
์ค์ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ ์, Vitest/Jest์ ๊ฐ์ ํ ์คํธ ํ๋ ์์ํฌ๊ฐ ์๊ตฌํ๋ ํ ์คํธ ํ์ผ์ ๊ธฐ๋ณธ ๊ตฌ์กฐ์ ๊ฐ ํค์๋์ ์ญํ ์ ๋จผ์ ์ดํดํ๊ธฐ.
1. describe: ํ ์คํธ ๊ทธ๋ฃนํ (Grouping)
- ๊ด๋ จ๋ ํ ์คํธ๋ค์ ๋ ผ๋ฆฌ์ ์ผ๋ก ๋ฌถ์ด์ฃผ๋ ํจ์. ์ผ๋ฐ์ ์ผ๋ก ํ ์คํธ ๋์ ์ปดํฌ๋ํธ๋ ๋ชจ๋์ ์ด๋ฆ์ผ๋ก ์ฌ์ฉ
describe('TodoInput ์ปดํฌ๋ํธ ํ
์คํธ', () => {
// ์ฌ๊ธฐ์ ๋ชจ๋ test() ํจ์๋ค์ด ๋ค์ด๊ฐ
});
2. test ๋๋ it: ๊ฐ๋ณ ํ ์คํธ ์ผ์ด์ค (Test Case)
- ์ค์ ๋ก ์ฝ๋๋ฅผ ์คํํ๊ณ ๊ฒ์ฆ(Assertion)์ ์ํํ๋ ๊ฐ์ฅ ์์ ๋จ์
- ํ๋์ test๋ ํ๋์ ๋ ๋ฆฝ์ ์ธ ์๋๋ฆฌ์ค๋ง ๊ฒ์ฆํ๋ ๊ฒ์ด ์ข์
- ํ ์คํธ์ ์ด๋ฆ์ "๋ฌด์์ ํ์ ๋ (When), ๋ฌด์์ด ๋์ด์ผ ํ๋ค (Should)"์ ๊ฐ์ด ์์ ์ ์ผ๋ก ์์ฑ
test('์ฌ์ฉ์๊ฐ ํ
์คํธ๋ฅผ ์
๋ ฅํ ์ ์๋ค', async () => {
// ..๊ถ์๋ ์ด์ฉ๊ตฌ
});
// 'it'๋ 'test'์ ์์ ํ ๋์ผํ ๊ธฐ๋ฅ.
it('๋ฒํผ์ ํด๋ฆญํ์ ๋ ํน์ ํจ์๊ฐ ํธ์ถ๋์ด์ผ ํ๋ค', () => {
});
3. Given-when-then ๋ฐฉ์์ ํ ์คํธ ์ผ์ด์ค ๊ตฌํ
ํจ์จ์ ์ด๊ณ ์ฝ๊ธฐ ์ฌ์ด ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด Given-When-Then (GWT) ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์.
์ด ํจํด์ ๋ชจ๋ ํ ์คํธ ์ผ์ด์ค์ ๋ช ํํ ํ๋ฆ๊ณผ ๋ชฉ์ ์ ๋ถ์ฌํจ
- Given
- ์ค๋น๋จ๊ณ, ํ ์คํธ์ ํ์ํ ์ด๊ธฐ ์กฐ๊ฑด(๋ ๋๋ง, Mock ํจ์)์ ์ค์
- When
- ์คํ ๋จ๊ณ, ํ ์คํธํ๋ ค๋ ํน์ ํ๋(์ฌ์ฉ์ ์ํธ์์ฉ)์ ์คํ
- Then
- assertion, ์คํ ๊ฒฐ๊ณผ๊ฐ ์์๋๋ก ๋ํ๋ฌ๋์ง expect๋ก ํ์ธ
test('๋ฒํผ ํด๋ฆญ ์ ํจ์๊ฐ ํธ์ถ๋์ด์ผ ํ๋ค', async () => {
// Given
const mockOnAdd = vi.fn();
render(<TodoInput onAddTodo={mockOnAdd} isLoading={false} />);
// When
await userEvent.click(screen.getByText('์ถ๊ฐ'));
// Then
expect(mockOnAdd).toHaveBeenCalled();
});
3. Setup/Teardown: ํ ์คํธ ํ๊ฒฝ ์ค๋น์ ์ ๋ฆฌ
- ํ ์คํธ๊ฐ ์คํ๋๊ธฐ ์ ํ์ ๋ฐ๋ณต์ ์ผ๋ก ํ์ํ ์ค๋น ์์ (Setup)๊ณผ ์ ๋ฆฌ ์์ (Teardown)์ ์ฒ๋ฆฌ
- ์ด๋ ํ ์คํธ ๊ฐ์ ๋ ๋ฆฝ์ฑ(Isolation)์ ์ ์งํ๋ ๋ฐ ๋งค์ฐ ์ค์
ํค์๋์คํ ์์ ์ญํ
| beforeEach | ๊ฐ test ํจ์ ์คํ ์ง์ | ๊ฐ ํ ์คํธ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ์คํ๋๋๋ก ์ด๊ธฐ ์ํ๋ฅผ ์ค์ ํ๊ฑฐ๋ Mocking์ ์ฌ์ค์ . (๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋จ) |
| afterEach | ๊ฐ test ํจ์ ์คํ ์งํ | ๊ฐ ํ ์คํธ๊ฐ ๋๋ ํ DOM์ ์ ๋ฆฌ(cleanup)ํ๊ฑฐ๋ Mocking ์ํ๋ฅผ ์ด๊ธฐํ. |
| beforeAll | describe ๊ทธ๋ฃน ์ ์ฒด ์์ ์ | ๋ชจ๋ ํ ์คํธ์ ๊ฑธ์ณ ํ ๋ฒ๋ง ํ์ํ ์ ์ญ ์ค์ (์: MSW worker ์์)์ ์ฒ๋ฆฌ. |
| afterAll | describe ๊ทธ๋ฃน ์ ์ฒด ์ข ๋ฃ ํ | ๋ชจ๋ ํ ์คํธ๊ฐ ๋๋ ํ ์ ์ญ ์์(์: MSW worker ์ข ๋ฃ)์ ํด์ |
4. ๊ตฌํํ๊ธฐ ์ ์ฃผ์ ๊ฐ๋ ๋ค
4.1. ์์ ๊ฒ์ (DOM Query)
- ์ฌ์ฉ์๊ฐ ์ ๊ทผํ ์ ์๋ ์์ฑ (Role, Text, Label ๋ฑ)์ ๊ธฐ์ค์ผ๋ก DOM ์์๋ฅผ ์ฐพ๋๋ค.
- getBy๋ ์์๋ฅผ ์ฐพ์ง ๋ชปํ๋ฉด ์๋ฌ๋ฅผ ๋ฐ์์ํค๊ณ , queryBy๋ null์ ๋ฐํ
screen.getByRole('button');
4.2. ๊ฐ ๊ฒ์ฆ (Assertion)
- ํน์ ๊ฐ์ด๋ ์์์ ์ํ๊ฐ ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ์ ์ผ์นํ๋์ง ํ์ธ
- RTL์ ์ปค์คํ Matchers (toBeInTheDocument ๋ฑ)์ Vitest/Jest์ ๊ธฐ๋ณธ Matchers (toHaveValue, toBe ๋ฑ)๋ฅผ ํจ๊ป ์ฌ์ฉ
expect(input).toHaveValue('๊ฐ');
4.3. ํจ์ ํธ์ถ ๊ฒ์ฆ
- Mock ํจ์ (vi.fn())๊ฐ ์๋๋๋ก ํธ์ถ๋์๋์ง, ๊ทธ๋ฆฌ๊ณ ํธ์ถ ์ ์ฌ๋ฐ๋ฅธ ์ธ์๋ฅผ ์ ๋ฌ๋ฐ์๋์ง ํ์ธ
expect(mockFn).toHaveBeenCalledWith('hello');
4.4. ํด๋ฆญ ์ด๋ฒคํธ (Interaction)
- ๋ฒํผ ํด๋ฆญ, ์ฒดํฌ๋ฐ์ค ํ ๊ธ ๋ฑ ๋ง์ฐ์ค ์ํธ์์ฉ์ ์ค์ ์ฌ์ฉ์์ฒ๋ผ ์๋ฎฌ๋ ์ด์
- userEvent๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด fireEvent๋ณด๋ค ์ค์ ๋ธ๋ผ์ฐ์ ์ ์ ์ฌํ๊ฒ ๋์ํ๋ฏ๋ก ๊ถ์ฅ
await userEvent.click(button);
4.5. ํค๋ณด๋ ์ ๋ ฅ (Interaction)
- ํ ์คํธ ์ ๋ ฅ, ์ํฐ ํค, ํญ ์ด๋ ๋ฑ ํค๋ณด๋ ์ํธ์์ฉ์ ์๋ฎฌ๋ ์ด์ ํ๋ฉฐ, onChange ์ด๋ฒคํธ์ ์ ๋ ฅ ์ํ๋ฅผ ์ ํํ๊ฒ ๋ฐ์
await userEvent.type(input, 'ํ
์คํธ');
4.6. ๋น๋๊ธฐ ๋๊ธฐ (Asynchronous)
- API ์๋ต, UI ์ ๋ฐ์ดํธ, ์ํ ๋ณ๊ฒฝ ๋ฑ ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋์ด ํน์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋๊น์ง ํ ์คํธ ํ๊ฒฝ์ ๋๊ธฐ
await waitFor(() => {
expect(screen.getByText('๊ฒฐ๊ณผ')).toBeInTheDocument();
});
5. ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ํ ์คํธ ๊ตฌํํ๊ธฐ
- Input ์ปดํฌ๋ํธ
- ๋ฆฌ์คํธ ์ปดํฌ๋ํธ
- ์ปค์คํ
ํ
- ๋ฆฌ์คํธ๊ฐ์ ธ์ค๊ธฐ, ์ถ๊ฐํ๊ธฐ, 500์๋ฌ ๋์ํ๊ธฐ
- ๋ชจํน vs. MSW
- MSW๋ฅผ ์ฐ๋ฉด fetch ๋ชจํน์ ์ ๊ฑฐํ๊ณ ์ค์ fetch๋ฅผ ๊ทธ๋๋ก ํ ์คํธํ๋๊น ๋ ๊น๋ํ๊ณ ์ ๋ขฐ๋๋ ๋์ํธ.
6. E2E ํ ์คํธ(End to End)
- ์ค์ ์ฌ์ฉ์๊ฐ ์๋น์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ๋ธ๋ผ์ฐ์ ํ๊ฒฝ ์ ์ฒด๋ฅผ ์๋ํํ์ฌ ํ ์คํธํ๋ ๋ฐฉ์
- ๊ฐ์ฅ๋์ ์ ๋ขฐ๋
- UI + Networking + Routing + DOM ๋ ๋๋ง
- ์ค์ ๋ธ๋ผ์ฐ์ ์์ ์คํ(chromium, webkit, firefox)
- ๋จ์๋ณด๋ค ๋๋ฆฌ์ง๋ง ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฒ์ฆํ ์ ์์
FE ๋๊ตฌ๋ค
- Cypress, Playwright
Playwright ํน์ง๋ค
- DOM์ด ๋ํ๋ ๋๊น์ง ์๋์ผ๋ก ๊ธฐ๋ค๋ฆฐ๋ค
- waitFor๋ฑ ๋ถํ์. ๋คํธ์ํฌ ์์ฒญ, ๋ ๋๋ง ์๋๊ฐ์ง
- DOM์์๋ฅผ ์ฝ๊ฒ ์ฐพ๋ํธ.
- ์ค๋ ์ต, ๋ นํ(recorder)๊ธฐ๋ฅ ์ ๊ณต.
- Codegen ์ผ๋ก ์๋ ํ ์คํธ์ฝ๋ ์์ฑ.
- ํ
์คํธ๊ฐ ๋๋๋ฉด ์๋์ผ๋ก HTML ๋ฆฌํฌํธ๋ฅผ ์์ฑ
- npx playwright show-report
playWright ์คํ์์
- Playwright test runner ์คํ
- ๋ธ๋ผ์ฐ์ ์๋ ์คํ
- ํ ์คํธ URL ์ ์
- ์ฌ์ฉ์์ ์ค์ ๋์์ ์๋ฎฌ๋ ์ด์
- DOM ์ํ ํ์ธ
- ํ ์คํธ ์ข ๋ฃ ๋ฐ ๋ธ๋ผ์ฐ์ ๋ซ๊ธฐ
- ๊ฒฐ๊ณผ ๋ฆฌํฌํธ ์ถ๋ ฅ (HTML ๋ฆฌํฌํธ ํฌํจ)
์ฌ์ฉ์์
๋ธ๋ผ์ฐ์ ์ด๊ธฐ
const browser = await chromium.launch();
์๋ก์ด ํ์ด์ง(page)๋ฅผ ์ฐ๋ค
const page = await browser.newPage();
ํน์ URL๋ก ์ด๋
await page.goto('http://localhost:5173/');
ํ๋์ ์๋ฎฌ๋ ์ด์
await page.fill('#todo-input', '์ฅ๋ณด๊ธฐ');
await page.click('button:has-text("์ถ๊ฐ")');
์ค์ DOM ์ํ๋ฅผ ํ์ธ
await expect(page.locator('li')).toContainText('์ฅ๋ณด๊ธฐ');
์๋ฃ ํ ๋ธ๋ผ์ฐ์ ์ข ๋ฃ
await browser.close();
7. TDD
Test driven development

8. Code Coverage
- ํ
์คํธ๊ฐ ์ฝ๋์ ๋ช %๋ฅผ ์คํํ๋์ง ๋ณด์ฌ์ฃผ๋ ์์น
- ์) ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง 80% → ์ ์ฒด ์ฝ๋ ์ค 80%๊ฐ ํ ์คํธ ์คํ ์ค ์ค์ ๋ก ์ํ๋จ
- ํ ์คํธ๊ฐ ์ถฉ๋ถํ ์์ฑ๋์๋์ง ํ์ธ
- CI/CD์์ ํ์ง ๊ธฐ์ค์ผ๋ก ์ผ๊ธฐ ์ข์
์ปค๋ฒ๋ฆฌ์ง์ ์ฃผ์ ์ ํ
- ๋ผ์ธ ์ปค๋ฒ๋ฆฌ์ง(Line Coverage): ๋ช ์ค์ด ์คํ๋๋๊ฐ
- ๋ธ๋์น ์ปค๋ฒ๋ฆฌ์ง(Branch Coverage): if/else ๋ฑ ๋ถ๊ธฐ๋ฌธ์ด ๊ฐ ์กฐ๊ฑด๋ง๋ค ์คํ๋๋๊ฐ
- ํจ์ ์ปค๋ฒ๋ฆฌ์ง(Function Coverage): ํจ์๋ค์ด ํธ์ถ๋๋๊ฐ
- ์คํ ์ดํธ๋จผํธ ์ปค๋ฒ๋ฆฌ์ง(Statement Coverage): ์คํ ๊ฐ๋ฅํ ๊ตฌ๋ฌธ(statement)์ด ์คํ๋๋๊ฐ
์ฃผ์์
- ์ปค๋ฒ๋ฆฌ์ง๊ฐ ๋๋ค๊ณ ํ ์คํธ ํ์ง์ด ๋์ ๊ฑด ์๋
- ์ค์ํ ๋ก์ง๋ง ์ ํ ์คํธํ๋ค๋ฉด ์ปค๋ฒ๋ฆฌ์ง๊ฐ ๋ฎ์๋ ๊ด์ฐฎ์ ์ ์์
'๐ ํ๋ก ํธ์๋(FE)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| ํ๋ก ํธ์๋ ์์ํ ํผ๋๋ฐฑ (0) | 2026.01.25 |
|---|---|
| Next.js ์์ํ๊ธฐ (1) | 2026.01.22 |
| FE ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ(FE ์ํคํ ์ณ) (0) | 2026.01.20 |
| React ์ํ๊ด๋ฆฌ ( ์ง์ญ, ์ ์ญ, ์๋ฒ ์ปดํฌ๋ํธ ) (0) | 2026.01.20 |
| React ์ฑ๋ฅ ์ต์ ํ (0) | 2026.01.20 |