1. ๋ค์ด๊ฐ๋ฉฐ
๋ฆฌ์กํธ ํ
์คํ
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค๋ณด๋ฉด, screen
, render
, fireEvent
๋ฑ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค.
์ด ๋ฉ์๋๋ค์ ์์ฃผ ์ฌ์ฉ๋๋๋ฐ์. scrren์ ์๋ก screen.getByText
์ ์ ๊ทผํ ๋ ์๋์์ฑ์ด ๋ฉ๋๋ค. ํ์ง๋ง screen
์ ํ์ดํ์ ์ง์ ํด์ฃผ์ด์ผ ํ๋๋ฐ์.
๊ทธ๋์ ์ด ์กฐ์ฐจ๋ ์๋์์ฑ์ด ๋๊ฒ ํ๋ฉด ํ์ดํ์ ์์ฐ์ฑ์ด ์ฌ๋ผ๊ฐ์ง ์์๊น ์๊ฐํ์ต๋๋ค. ์ด๋ฒ ํฌ์คํ
์์๋ ์ด๋ฌํ ํ
์คํ
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฉ์๋๋ค์ ํ์
์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํ์ฌ ์๋ ์์ฑ์ผ๋ก ์ฌ์ฉํด ๋ณธ ๊ฒฝํ๋ด์ ๋ด์์ต๋๋ค.
2. d.ts ํ์ ์ ์ธ์ผ๋ก ๋ฆฌ์กํธ ํ ์คํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฉ์๋ ์๋ ์์ฑ ํ์ฉํ๊ธฐ
๋จผ์ @testing-library/react
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์กด์ฑ์์ screen, render๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
import { render, screen } from '@testing-library/react';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
๋จผ์ ์๊ฐ ๋๋ ์์ด๋์ด๋ _t.
๋ฅผ ํ๋ฉด ์๋ ์์ฑ์ผ๋ก ์์ฃผ ์ฐ๋ ๋ฉ์๋ ๋ค์ ๋์ค๊ฒ ํ๋ฉด ์ด๋จ๊น ์๋๋ฐ์.
์ด ์์ด๋์ด๋ฅผ ์คํํ๊ธฐ ์ํด์ ๋จผ์ ์์๋ก screen. ์์ ๋ฉ์๋๋ค์ ์ด๋ป๊ฒ ์ ์๋์๋์ง ํ์
์ ์ ํ์ผ์ ํ์ธํด ๋ด
๋๋ค. @testing-library/react
์ ํ์
์ ์ธ ํ์ผ(.d.ts ํ์ผ)์ node_modules/@testing-library/react ๋๋ ํ ๋ฆฌ ์๋์ ์์นํด ์๋๋ฐ์.
screen
์ด ๋๋ถ์ screen ์ ์์ฑ๋ค์ ๋ชจ๋ ์๋์์ฑ์ด ๋ฉ๋๋ค.
๊ทธ๋ผ _t๋ฅผ ํตํด screen, render ๊ฐ ๋์ค๊ฒ ํ๋ ค๋ฉด ํ์ฌ ํ๋ก์ ํธ์ ํ์ ์ ์ธ ํ์ผ์์ ํ์ ์ ์ง์ ํด์ค์ผ ํฉ๋๋ค.
ํ์ ์ ์ ํ์ผ์ ์ฌ์ฉํ๋ฉด ํ์ ์คํฌ๋ฆฝํธ ์ปดํ์ผ๋ฌ์๊ฒ ํน์ ์ ์ญ ๋ณ์๊ฐ ์์์ ์๋ฆฌ๊ฒ ๋๊ณ ํ์ ์ฒดํฌ์ ์๋์์ฑ ๊ธฐ๋ฅ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ์ด ํ์ผ๋ด์์ ์์ฑํ๊ฒ ๋๋ฉด ํ๋ก์ ํธ ๋ด ์ด๋์๋ ์ ๊ทผํ ์ ์๊ฒ ๋ฉ๋๋ค. ์ฆ ์ ์ญ ์ค์ฝํ์ ํ์ ์ ๋ณด๋ฅผ ์ถ๊ฐ ํ ์ ์์ต๋๋ค.
๋จผ์ ์๋์์ฑ์ผ๋ก ์ค์ ํ ๋ฉ์๋๋ค์ ๊ฐ์ฒด์ ๋ด์๋ก๋๋ค.
export const testUtils = {
render,
screen,
fireEvent,
renderHook,
act,
}
//global.d.ts
import { testUtils } from '@/types/test-utils'
declare global {
const _t: typeof testUtils
}
export {}
jest.setup ํ์ผ์์ ๊ธ๋ก๋ฒ๋ก ์ ์ธํด๋ _t ๋ณ์๋ฅผ ๋ฐํ์์ ์ฌ์ฉํ ์ ์๊ฒ globalThis ๊ฐ์ฒด ๋ด _t๋ฅผ ์ ์ธํฉ๋๋ค.
์ jest.setup ํ์ผ์์ _t ๋ฅผ ๋ค์ ํ ๋นํ์ฃ ? โ
. declare global
๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ TypeScript์ ์ ์ญ ๋ณ์์ ์กด์ฌ์ ํ์ ์ ์๋ฆฌ๋ ๊ฒ๋ง์ผ๋ก๋ ์ค์ ๋ฐํ์ ํ๊ฒฝ์์ ์ ์ญ ๋ณ์๊ฐ ์ ์๋์ง ์์ต๋๋ค. ๋ฐ๋ผ์, setup.ts์ ๊ฐ์ ์ด๊ธฐํ ํ์ผ์์ ์ค์ ๋ก ์ ์ญ ๋ณ์๋ฅผ ์ค์ ํด์ค์ผ ํฉ๋๋ค.
//jest.setup.ts
Object.defineProperty(globalThis, '_t', {
value: testUtils,
writable: false,
configurable: false,
})
_t.
์ ํ๋ฉด ์๋์์ฑ์ผ๋ก ์ถ๋ก ๋๋ ๋ฉ์๋๋ค์ด ๋ณด์
๋๋ค.
์ด์ ํ ์คํธ๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
//test
it('์์ดํ
์ด ์ ์ผ ์ผ์ชฝ์ ์์น ํ๊ณ ์์ ๋, ์ผ์ชฝ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ ์ด์ ์ด๋ ํ์ง ์๋๋ค.', () => {
_t.render(<Carousel>{childArray}</Carousel>)
const track = _t.screen.getByTestId('carousel_track')
const prevButton = _t.screen.getByTestId('carousel_prev_button')
expect(track).toHaveStyle('transform: translateX(-0px)')
_t.fireEvent.click(prevButton)
expect(track).toHaveStyle('transform: translateX(-0px)')
})
3. DX ๋ฐ ๊ฐ๋ ์ฑ ๋น๊ต
ํ์ดํ์ ์๋๊ฐ์ ๋นจ๋ผ์ก๋ค๊ณ ์๊ฐ๋๊ณ ํธํ๊ธฐ๋ ํ๋๋ฐ์. ๊ทธ๋ผ ๊ฐ๋ ์ฑ์ ์ด๋จ๊น์?
์ฝ๋์ ์ ํ๋ฅผ ๋น๊ตํด ๋ณผ๊ฒ์.
์ด๋ค๊ฐ์??
์ ๋ ๊ฐ์ธ์ ์ผ๋ก ํ์ดํ์ ๊ฒฝํ์ ์ข์์ง๋ง, ๊ฐ๋ ์ฑ์ ๊ธฐ์ค์ผ๋ก ๋ค์ ๋ณด๋ ํ ์คํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ ์ ์ธ์ ๋ถ๋ถ์ ๋ฐฉํด ํ๊ณ ์๋จ ๋๋์ ๋ฐ์๋๋ฐ์.
ํ ์คํธ ํ๊ฒฝ์์๋ ๊ฐ๊ฒฐํ๊ณ ์ ์ธ์ ์ธ ์ฝ๋๊ฐ ์ค์ํ๋ฐ, DX๋ฅผ ์งํฅํ๋ ค๊ณ ํ๋ค ๋ณด๋ ๊ณผ๋ํ๊ฒ ๋์ด๋ฒ๋ ธ๊ณ ๊ฐ๋ ์ฑ๋ฉด ์์ ์กฐ๊ธ์ ํด์น ์ ์๊ฒ ๋ค๋ผ๋ ์๊ฐ์ด ๋ค์์ต๋๋ค.
3. ๋ง๋ฌด๋ฆฌ
๋ฆฌ์กํธ ํ
์คํ
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฉ์๋๋ค์ ์๋ ์์ฑํ ๊ฒฝํ์ ํ๋๋ฐ์. declare
๋ ํ์ฉ ํ๋ ๊ธฐํ๋ ๋์์ง๋ง, ๊ฐ๋ฐ์ ๊ฒฝํ๊ณผ ๊ฐ๋
์ฑ ์ฌ์ด์ ๊ท ํ์ ์ ์งํ๋ ๊ฒ์ด ์ค์ํจ์ ๋๊ผ์ต๋๋ค.