React Testing Library는 React 컴포넌트를 테스트할 때 DOM 요소를 쉽게 찾고 검사할 수 있는 다양한 쿼리 메서드를 제공합니다. 이러한 메서드는 특정 요소가 DOM에 있는지 확인하거나, 없어야 하는지 확인하거나, 비동기적으로 나타나는 요소를 다룰 때 유용합니다. 이번 글에서는 screen 객체의 쿼리 메서드를 중심으로, getBy, queryBy, findBy 메서드들이 어떻게 동작하는지 알아보겠습니다.
screen 객체는 React Testing Library에서 제공하는 글로벌 객체로, DOM에서 요소를 검색할 수 있는 다양한 메서드를 포함하고 있습니다. 이 메서드들은 command[All]ByQueryType
이라는 형식으로 구성됩니다. 여기서 command는 메서드의 동작 방식(예: get, query, find)을, QueryType은 검색 방식(예: Role, Text, LabelText)을 나타냅니다.
command 부분은 쿼리 메서드가 요소를 찾을 때 어떻게 동작하는지를 결정합니다. React Testing Library에서 가장 많이 사용되는 command에는 get, query, find가 있습니다.
: 요소가 DOM에 반드시 존재해야 할 때 사용합니다. 요소를 찾지 못하면 즉시 에러를 던지며, 테스트는 실패합니다. 주로 동기적인 상황에서 사용됩니다.
const button = screen.getByRole('button', { name: /submit/i });
expect(button).toBeInTheDocument();
: 요소가 DOM에 존재하지 않거나
, 있을 수도 있는 경우에 사용됩니다. 요소가 존재하지 않으면 null을 반환
하므로, 에러를 던지지 않고 계속해서 테스트를 진행할 수 있습니다.
const modal = screen.queryByRole('dialog');
expect(modal).not.toBeInTheDocument();
: 요소가 비동기적
으로 나타날 것을 예상할 때 사용합니다. 이 메서드는 Promise를 반환하며, 요소가 나타날 때까지 기다립니다. 지정된 시간 내에 요소를 찾지 못하면 에러를 던집니다.
const alert = await screen.findByRole('alert');
expect(alert).toBeInTheDocument();
QueryType 부분은 DOM에서 요소를 찾는 방법을 정의합니다. React Testing Library는 다양한 QueryType을 제공하며, 이들을 사용해 더 구체적인 요소를 찾을 수 있습니다. 주요 QueryType으로는 Role, Text, LabelText, PlaceholderText 등이 있습니다.
ByRole
: 요소의 ARIA 역할을 기준으로 검색합니다. 버튼, 제목, 텍스트 상자 등과 같은 요소를 검색할 때 주로 사용됩니다.const button = screen.getByRole('button', { name: /submit/i });
ByText
: 요소의 텍스트 내용을 기준으로 검색합니다. 특정 텍스트가 포함된 요소를 찾을 때 유용합니다.const heading = screen.getByText(/welcome/i);
ByLabelText
: label 요소와 연결된 폼 요소를 기준으로 검색합니다. 폼의 접근성 속성을 테스트할 때 자주 사용됩니다.const input = screen.getByLabelText(/username/i);
다음 표는 getBy, queryBy, findBy 메서드들이 특정 조건에서 어떻게 동작하는지를 요약한 것입니다.
getBy
and getAllBy
const buttons = screen.getAllByRole('button');
expect(buttons.length).toBeGreaterThan(1);
getBy
: 메서드는 DOM에서 요소를 찾지 못하면 에러를 던지며, 요소를 하나만 찾을 경우 이를 반환합니다. 만약 여러 요소가 일치한다면 에러가 발생합니다. 주로 요소가 반드시 존재해야 하는 상황에서 사용됩니다.
getAllBy
: 메서드는 여러 개의 요소를 찾는 데 사용됩니다. 요소를 찾지 못하면 에러를 던지며, 하나 이상의 요소를 찾으면 배열로 반환합니다.
queryBy
and queryAllBy
const items = screen.queryAllByRole('listitem');
expect(items).toHaveLength(0);
queryBy
: 메서드는 요소를 찾지 못했을 때 null을 반환
합니다. 요소가 존재하지 않거나 선택적으로 존재할 수 있는 상황에서 사용됩니다.queryAllBy
: 여러 개의 요소를 찾지만, 요소를 찾지 못해도 에러를 던지지 않고 빈 배열을 반환
합니다.findBy
and findAllBy
const alerts = await screen.findAllByRole('alert');
expect(alerts).toHaveLength(2);
findBy
: 메서드는 비동기적
으로 요소가 DOM에 나타날 것을 기대할 때 사용됩니다. Promise를 반환하며, 요소가 나타날 때까지 기다립니다. 지정된 시간 내에 요소를 찾지 못하면 에러가 발생합니다.findAllBy
: 여러 개의 요소가 비동기적
으로 나타날 것을 기대할 때 사용되며, 요소들이 나타날 때까지 기다린 후 배열로 반환합니다.요소가 반드시 존재해야 하는 경우: getBy
메서드 사용. 예를 들어, "로그인" 버튼이 반드시 있어야 하는 경우, getByRole을 사용하여 버튼이 존재하는지 확인합니다.
요소가 존재하지 않아야 하는 경우: queryBy
메서드 사용. 예를 들어, 특정 상태에서 "에러 메시지"가 나타나지 않아야 한다면, queryByText를 사용해 메시지가 존재하지 않음을 확인합니다.
비동기적으로 요소가 나타나는 경우: findBy
메서드 사용. API 호출 이후에 나타나는 요소를 기다려야 하는 경우, findByRole을 사용하여 해당 요소가 나타나는지 확인할 수 있습니다.
여러 개의 요소가 있을 수 있는 경우: getAllBy, queryAllBy, findAllBy
메서드 사용. 예를 들어, 여러 개의 체크박스를 테스트할 때는 getAllByRole을 사용해 모든 체크박스가 렌더링되었는지 확인할 수 있습니다.
참고 문서