React Testing Library로 통합 테스트하기
테스트에서 컴포넌트를 렌더링하고 이벤트를 발생시키며 구현이 아닌 화면에 보이는 출력 결과를 검증합니다.
React Testing Library로 통합 테스트하기은(는) CoddyKit의 무료 React Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 React Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
React Testing Library란 무엇인가요
React Testing Library(RTL)는 사용자 관점에서 테스트하도록 권장합니다. 컴포넌트를 렌더링하고, 사용자처럼 상호 작용하며, 구현 세부 정보가 아닌 화면에 표시되는 결과를 검증합니다.
설정
RTL은 Create React App과 Vite의 React 템플릿에 포함되어 있습니다. 수동으로 설정하려면 @testing-library/react와 @testing-library/jest-dom을 설치하십시오.
// package.json
// "@testing-library/react": "^14.0.0",
// "@testing-library/jest-dom": "^6.0.0"
// setupTests.ts
import '@testing-library/jest-dom';컴포넌트 렌더링
render()는 가상 DOM에 컴포넌트를 마운트합니다. 렌더링된 출력 범위로 제한된 조회 함수를 반환합니다.
import { render, screen } from '@testing-library/react';
import { Button } from './Button';
test('renders button label', () => {
render(<Button label="Submit" onClick={() => {}} />);
expect(screen.getByText('Submit')).toBeInTheDocument();
});요소 조회하기
다음 순서로 조회 함수를 우선 사용하십시오: getByRole > getByLabelText > getByPlaceholderText > getByText. 역할 조회는 접근성 의미론에 맞는 요소를 찾습니다.
// Best: query by role
const button = screen.getByRole('button', { name: /submit/i });
// Good: query by label (for form inputs)
const input = screen.getByLabelText('Email address');
// Acceptable: query by text
const heading = screen.getByText('Welcome');이벤트 발생시키기
@testing-library/user-event의 userEvent를 우선 사용하고, 기본적인 경우에는 fireEvent를 사용하십시오. userEvent는 포커스와 포커스 해제를 포함한 실제 브라우저 상호 작용을 시뮬레이션합니다.
import userEvent from '@testing-library/user-event';
test('types into input', async () => {
const user = userEvent.setup();
render(<SearchBar />);
const input = screen.getByRole('textbox');
await user.type(input, 'react');
expect(input).toHaveValue('react');
});양식 제출 테스트
양식을 렌더링하고 userEvent.type으로 입력 요소를 채운 다음 제출 버튼을 클릭하고 결과를 검증하십시오. 결과에는 성공 메시지, 페이지 이동 또는 콜백 호출이 포함될 수 있습니다.
test('submits the login form', async () => {
const onLogin = jest.fn();
const user = userEvent.setup();
render(<LoginForm onLogin={onLogin} />);
await user.type(screen.getByLabelText('Email'), 'test@example.com');
await user.type(screen.getByLabelText('Password'), 'password123');
await user.click(screen.getByRole('button', { name: /log in/i }));
expect(onLogin).toHaveBeenCalledWith({ email: 'test@example.com', password: 'password123' });
});표시 여부 검증
toBeInTheDocument(), toBeVisible(), toHaveValue()와 같은 jest-dom 매처를 사용하면 검증을 읽기 쉽게 작성할 수 있습니다.
expect(screen.getByText('Error: required')).toBeInTheDocument();
expect(screen.getByRole('dialog')).toBeVisible();
expect(screen.getByRole('textbox')).toHaveValue('hello');
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();조건부 렌더링 테스트
요소가 렌더링되지 않았는지 확인하려면 요소가 없을 때 null을 반환하는 queryBy를 사용하십시오. 요소가 있어야 한다면 getBy를 사용하십시오.
test('shows error message when validation fails', async () => {
const user = userEvent.setup();
render(<SignUpForm />);
await user.click(screen.getByRole('button', { name: /submit/i }));
expect(screen.getByText('Email is required')).toBeInTheDocument();
});프로바이더로 감싸기
대부분의 컴포넌트에는 컨텍스트 또는 라우터가 필요합니다. render 호출 안에서 프로바이더로 컴포넌트를 감싸거나 사용자 지정 renderWithProviders 도우미를 만드십시오.
function renderWithProviders(ui: React.ReactElement) {
return render(
<QueryClientProvider client={new QueryClient()}>
<MemoryRouter>
{ui}
</MemoryRouter>
</QueryClientProvider>
);
}
test('shows user data', () => {
renderWithProviders(<UserProfile />);
});상태 변경 테스트
컴포넌트에 동작을 수행한 다음 새로운 상태가 사용자 인터페이스에 반영되었는지 검증하십시오. userEvent를 사용하면 RTL이 대부분의 상호 작용을 자동으로 act로 감쌉니다.
test('counter increments', async () => {
const user = userEvent.setup();
render(<Counter />);
expect(screen.getByText('Count: 0')).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: /increment/i }));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});화면 디버그 도우미
현재 렌더링된 HTML을 콘솔에 출력하려면 screen.debug()를 호출하십시오. 조회가 실패했을 때 실제로 무엇이 렌더링되었는지 확인하는 데 유용합니다.
test('debugging a failing query', () => {
render(<MyComponent />);
screen.debug(); // prints rendered HTML
screen.getByRole('button', { name: /save/i }); // then inspect output
});빠른 확인
React Testing Library에서 버튼을 테스트할 때 어떤 조회 함수를 우선 사용해야 하나요?
요약
RTL은 역할 기반 조회와 userEvent를 통해 컴포넌트를 렌더링하고 상호 작용합니다. 필요한 프로바이더로 컴포넌트를 감싸고, 읽기 쉬운 검증을 위해 jest-dom 매처를 사용하며, 요소가 없는지 확인할 때는 queryBy를 우선 사용하십시오.
자주 묻는 질문
“React Testing Library로 통합 테스트하기” 강의는 무료인가요?
네 — “React Testing Library로 통합 테스트하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 React Academy 강의 전체를 잠금 해제할 수 있습니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“React Testing Library로 통합 테스트하기”에서 뭘 배우나요?
테스트에서 컴포넌트를 렌더링하고 이벤트를 발생시키며 구현이 아닌 화면에 보이는 출력 결과를 검증합니다. 브라우저에서 직접 실행하는 실습 코드로 React Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
React Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 React Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“React Testing Library로 통합 테스트하기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 React Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 React Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- React Testing Library로 통합 테스트하기
- MSW로 비동기 UI와 API 호출 테스트하기
- React용 Playwright 시작하기
- 양식과 사용자 흐름 엔드 투 엔드 테스트