[Svelte 시리즈 16편] 컴포넌트 테스트 전략

English version

접근성을 챙겼다면 이제 동작을 자동으로 검증할 차례입니다.

이번 글에서 새로 나오는 용어

  1. 단위 테스트: 컴포넌트 하나나 함수 하나를 따로 떼어 기대한 출력이 나오는지 확인하는 자동화 코드입니다.
  2. 통합 테스트: 여러 컴포넌트·스토어·로드 함수가 함께 돌아갈 때도 문제가 없는지 확인하는 시나리오형 테스트입니다.
  3. Vitest: Vite 프로젝트에 맞춰 빠르게 실행되는 자바스크립트 테스트 러너입니다.
  4. Svelte Testing Library: 실제 사용자처럼 DOM을 찾아 상호작용하는 테스트 도구 모음입니다.

핵심 개념

단위 테스트(unit test, 단위 검증)는 작은 컴포넌트를 독립적으로 확인하는 절차입니다. 통합 테스트(integration test, 통합 검증)는 여러 컴포넌트나 load 함수가 함께 동작하는지를 확인합니다. Vitest는 Vite 기반 프로젝트에 잘 맞는 테스트 러너입니다. Svelte Testing Library는 사용자 관점의 DOM 접근 방식을 제공합니다.

코드로 따라하기

설정, 렌더 테스트, 이벤트 테스트, load 함수 테스트를 순서대로 봅니다.

// vitest.config.ts

export default defineConfig({
  plugins: [svelte()],
  test: {
    environment: 'jsdom'
  }
});

test('카드가 제목과 담당자를 보여 준다', () => {
  const task = { title: '정적 분석', assignee: '유나', done: false };
  const { getByText } = render(TaskCard, { props: { task } });
  expect(getByText('정적 분석')).toBeInTheDocument();
  expect(getByText('유나')).toBeInTheDocument();
});

test('완료 버튼 클릭 시 toggle 이벤트 발생', async () => {
  const task = { title: '문서 작성', done: false };
  const { component, getByRole } = render(TaskCard, { props: { task } });
  const spy = vi.fn();
  component.$on('toggle', spy);
  await fireEvent.click(getByRole('button', { name: /완료/ }));
  expect(spy).toHaveBeenCalledTimes(1);
});

test('load는 주제와 과제를 병렬로 불러온다', async () => {
  const fetch = vi.fn()
    .mockResolvedValueOnce({ json: () => Promise.resolve([]) })
    .mockResolvedValueOnce({ json: () => Promise.resolve([]) });
  const data = await load({ fetch, parent: () => ({}) });
  expect(fetch).toHaveBeenCalledTimes(2);
  expect(data).toEqual({ subjects: [], tasks: [] });
});

이렇게 하면 UI와 서버 로직이 모두 안정적으로 동작하는지 빠르게 확인할 수 있습니다.

기대 출력 확인

테스트는 코드보다 결과 화면이 더 중요할 때가 많습니다.

:::terminal{title="Vitest 실행 결과 예시", showFinalPrompt="false"}

[
  { "cmd": "pnpm vitest run", "output": "✓ src/lib/components/TaskCard.test.ts (2)\n✓ src/lib/components/TaskForm.test.ts (1)\n✓ src/routes/dashboard/+page.server.test.ts (1)\n\nTest Files  3 passed\nTests       4 passed\nDuration    1.12s", "delay": 500 }
]

:::

  • 확인할 점: 어떤 파일이 통과했는지 한눈에 보이는지
  • 확인할 점: 컴포넌트 테스트와 load 테스트가 같이 돌아가는지
  • 확인할 점: 실패가 나면 어느 파일을 먼저 열어야 하는지 바로 판단되는지

왜 중요한가

작은 팀에서는 사람이 직접 모든 화면을 확인하기 어렵습니다. 테스트를 작성해 두면 리팩터링이나 버전 업그레이드 후에도 기존 기능이 깨지지 않았다는 확신을 얻을 수 있습니다.

실습

  • 따라 하기: vitest.config.ts를 설정하고 TaskCard 렌더 테스트를 작성한다.
  • 확장하기: 이벤트 테스트와 load 함수 테스트를 추가해 비동기 흐름을 검증한다.
  • 디버깅: 실패 메시지가 나오면 테스트 데이터가 실제 props 구조와 일치하는지 확인한다.
  • 완료 기준: pnpm test 실행 시 최소 세 가지 테스트가 통과한다.

마무리

테스트 자동화는 이후 실시간 기능이나 배포 과정에서도 든든한 안전망이 됩니다. 다음 편에서는 실시간 업데이트 패턴으로 경험을 확장합니다.

💬 댓글

이 글에 대한 의견을 남겨주세요