React Testing

geun·2025년 3월 24일

React

목록 보기
13/14
post-thumbnail

1. Setup

Vite 환경의 프로젝트에서 react-testing-library로 테스트를 할때 사용하므로 다음 라이브러리를 설치해야 한다.
설치

npm install --save-dev @testing-library/react @testing-library/jest-dom vitest

환경설정

// setupTests.ts
import '@testing-library/jest-dom';
import { expect } from 'vitest';
import matchers from '@testing-library/jest-dom/matchers';

expect.extend(matchers);

// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/setupTests.ts'
  }
});

2. Component Testing

2.1 Component with Props Testing

컴포넌트가 props를 받아 동적으로 렌더링되는 경우, 해당 props가 올바르게 반영되는지를 테스트해야 한다.

// UserStatus.test.tsx
import React from 'react';
import { render, screen } from '@testing-library/react';
import UserStatus from '../../src/components/UserStatus';

describe('UserStatus Component', () => {
  it('displays a welcome message when an email is provided', () => {
    render(<UserStatus email="user@example.com" />);
    
    const welcomeMessage = screen.getByText(/Welcome/i);
    expect(welcomeMessage).toBeInTheDocument();
  });
});

위 코드는 UserStatus 컴포넌트가 전달받은 이메일에 따라 환영 메시지를 출력해지는 코드를 테스트한 코드이다. 정규 표현식을 통해 Welcome이라는 메시지의 존재 유무를 파악하여 테스팅 결과를 알려준다.

2.2 List Component Testing

리스트 컴포넌트를 테스트할 때는 여러 아이템이 렌더링 되는지, 각 아이템이 올바른 정보를 담고 있는지를 확인한다.

// ListComponent.test.tsx
import React from 'react';
import { render, screen } from '@testing-library/react';
import ListComponent from '../../src/components/ListComponent';

describe('ListComponent', () => {
  it('renders all list items correctly', () => {
    const items = ['Apple', 'Banana', 'Cherry'];
    render(<ListComponent items={items} />);
    
    items.forEach(item => {
      expect(screen.getByText(item)).toBeInTheDocument();
    });
  });
});

다음 코드는 배열을 props로 전달받는 컴포넌트에서 forEach 메서드를 통해 모든 요소가 제대로 렌더링 되는지를 확인하는 방식이다.

3. Screen Object Methods

React Testing Library에서는 DOM 요소를 찾기 위해 screen 객체를 사용하는데, 이 객체는 다음과 같이 다양한 메서드를 제공한다.

getBy* : 요소가 반드시 존재해야 하며, 없으면 에러 발생

getAllBy* : 조건에 맞는 모든 요소를 배열로 반환

queryBy* : 요소가 없으면 null을 반환하며, 존재하면 요소를 반환

queryAllBy* : 조건에 맞는 모든 요소를 배열로 반환하며, 없으면 빈 배열 반환

findBy* : 비동기 상황에서 요소를 기다리며, Promise를 반환

findAllBy* : 비동기 상황에서 모든 요소를 기다리며, Promise를 반환

각 메서드는 특정 상황에 맞게 선택적으로 사용하면 된다.

3.1 getByRole

getByRole은 접근성을 고려하여 요소의 역할(role)에 따라 요소를 선택한다.
예를 들어, 버튼 요소를 찾으려면 다음과 같이 사용할 수 있다.

const button = screen.getByRole('button', { name: /submit/i });
expect(button).toBeInTheDocument();

이러한 방식은 사용자 관점에서 요소를 선택하기에 권장되는 편이다.

3.2 All getBys

getByText, getByLabelText, getByPlaceholderText 등
이 계열의 메서드는 요소의 text, label, placeholder 등을 기준으로 요소를 선택한다.

const heading = screen.getByText(/welcome to react testing/i);
const input = screen.getByPlaceholderText(/enter your name/i);

이 메서드들은 찾는 요소가 반드시 존재해야 하므로, 조건이 맞지 않으면 에러가 발생한다.

3.3 All getAllBys

getAllBy* 메서드는 조건에 맞는 여러 요소를 배열로 반환한다. 리스트나 여러 동일 요소들을 찾을 때 유용하다.

const listItems = screen.getAllByRole('listitem');
expect(listItems.length).toBeGreaterThan(0);

여러 요소가 렌더링 되어야 하는 경우 사용하며, 결과가 빈 배열이면 테스트에서 에러로 처리된다.

3.4 All queryBys

queryBy* 메서드는 조건에 맞는 요소가 없을 때 에러를 발생시키지 않고 null을 반환한다.예를 들어, 특정 텍스트가 렌더링되지 않아야 할 때 사용한다.

const errorMessage = screen.queryByText(/error/i);
expect(errorMessage).toBeNull();

3.5 All queryAllBys

queryAllBy* 메서드는 조건에 맞는 모든 요소를 배열로 반환한다. 요소가 없으면 빈 배열을 반환하기 때문에, 부재 여부를 확인할 때도 사용할 수 있다.

const buttons = screen.queryAllByRole('button');
expect(buttons).toHaveLength(0); // 버튼이 렌더링되지 않아야 하는 경우

3.6 All findBys

비동기 렌더링이 발생할 때 findBy* 메서드를 사용한다. 이 메서드는 Promise를 반환하므로, await을 사용하여 결과를 기다린다.

const asyncListItems = await screen.findAllByRole('listitem');
expect(asyncListItems.length).toBeGreaterThan(0);

데이터를 가져오는 비동기 작업 후 요소가 렌더링 되는 경우에 사용할 수 있다.

3.7 All findAllBys

findAllBy* 메서드는 조건에 맞는 여러 요소를 비동기적으로 기다린다.

const asyncListItems = await screen.findAllByRole('listitem');
expect(asyncListItems.length).toBeGreaterThan(0);

비동기 상황에서 여러 요소가 렌더링 되는지를 테스트할 때 사용할 수 있다.

4. 📌 getBy* vs queryBy* vs findBy*

메서드특징
getBy*요소가 반드시 존재해야 하며, 없으면 에러 발생
queryBy*요소가 없으면 null을 반환
findBy*요소가 비동기로 렌더링될 경우, Promise를 반환

0개의 댓글