mason
mason-log.

mason

mason.

안녕하세요. mason 입니다.

testing

Testing Library.

사용자 관점으로 UI를 검증하는 Testing Library. 쿼리 우선순위, user-event, 안티패턴.

Testing Library(React Testing Library 등)는 컴포넌트를 구현 디테일이 아니라 사용자가 보고 누르는 방식으로 테스트하게 돕는 라이브러리다.

The more your tests resemble the way your software is used, the more confidence they can give you.

❓ 왜 쓰나

  • component.state.x처럼 내부 state를 직접 건드리면, 리팩터만 해도 테스트가 깨지기 쉽다.
  • 화면 텍스트, 역할(role), 라벨로 요소를 찾으면 실제 사용과 가까운 회귀를 잡는다.

📘 기본 흐름 (React)

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LoginForm } from './LoginForm';

it('submits email', async () => {
  const user = userEvent.setup();
  render(<LoginForm />);

  await user.type(screen.getByLabelText('이메일'), 'a@b.com');
  await user.click(screen.getByRole('button', { name: '로그인' }));

  expect(await screen.findByText('환영합니다')).toBeInTheDocument();
});

역할 나누기:

  • render → 화면 올리기
  • getBy* / findBy* → 요소 찾기
  • userEvent → 클릭, 타이핑 (fireEvent보다 이쪽을 우선)

🧪 쿼리 우선순위

권장 순서는 아래와 같다.

  1. Accessible
    • getByRole
    • getByLabelText
    • getByPlaceholderText
  2. Semantic
    • getByText
    • getByDisplayValue
  3. Test id (최후)
    • getByTestId — 접근성으로 찾기 어려울 때만

같은 이름이면 시점을 구분한다.

  • getBy — 없으면 바로 실패
  • queryBy — 없으면 null
  • findBy — 비동기 등장 대기

⚠️ 안티패턴

  • 클래스명, 컴포넌트 인스턴스, 내부 state를 단언하기
  • waitFor 없이 비동기 UI를 바로 getBy로 잡기
  • 스냅샷만으로 UI 회귀를 전부 맡기기

⚛️ React / Vue

  • React: @testing-library/react
  • Vue: @testing-library/vue
  • 철학은 같고, 렌더 API만 프레임워크에 맞게 바뀐다.

🔗 러너와의 관계

  • Testing Library → 어떻게 렌더하고 질의할지
  • Jest / Vitest → 그 테스트를 언제 돌릴지
  • 둘은 같이 쓰는 조합이 일반적이다.

🔗 참고 자료