🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Testing 기초부터 심화까지 완벽 가이드 - 슬라이드 1/13
A

AI Generated

2025. 11. 3. · 18 Views

Testing 기초부터 심화까지 완벽 가이드

소프트웨어 테스팅의 핵심 개념부터 고급 테스팅 패턴까지 다룹니다. 단위 테스트, 통합 테스트, E2E 테스트, Mocking, TDD 등 실무에서 필요한 모든 테스팅 기법을 학습합니다.


카테고리:JavaScript
언어:JavaScript
메인 태그:#Testing
서브 태그:
#Jest#UnitTest#Mocking#TDD

들어가며

이 글에서는 Testing 기초부터 심화까지 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. 기본_단위_테스트
  2. 비동기_코드_테스트
  3. Mock_함수_활용
  4. 모듈_Mocking
  5. 테스트_전후_설정
  6. Matcher_활용
  7. 예외_처리_테스트
  8. Snapshot_테스팅
  9. 테스트_커버리지
  10. TDD_실습
  11. 통합_테스트
  12. 테스트_조직화

1. 기본 단위 테스트

개요

함수나 모듈의 가장 작은 단위를 검증하는 테스트입니다. Jest를 사용한 기본적인 테스트 작성법을 보여줍니다.

코드 예제

function sum(a, b) {
  return a + b;
}

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

설명

test 함수로 테스트 케이스를 정의하고, expect와 toBe matcher로 결과값을 검증합니다. 가장 기본적인 테스트 패턴입니다.


2. 비동기 코드 테스트

개요

Promise나 async/await를 사용하는 비동기 함수를 테스트하는 방법입니다. API 호출 등을 검증할 때 필수적입니다.

코드 예제

async function fetchUser(id) {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}

test('fetches user data', async () => {
  const user = await fetchUser(1);
  expect(user.name).toBe('John');
});

설명

async/await를 사용하여 비동기 함수의 결과를 기다린 후 검증합니다. test 함수도 async로 선언해야 합니다.


3. Mock 함수 활용

개요

실제 함수 대신 가짜 함수를 사용하여 호출 여부, 호출 횟수, 전달된 인자 등을 검증합니다.

코드 예제

const mockCallback = jest.fn(x => x + 1);

[1, 2, 3].forEach(mockCallback);

expect(mockCallback).toHaveBeenCalledTimes(3);
expect(mockCallback).toHaveBeenCalledWith(1);
expect(mockCallback.mock.results[0].value).toBe(2);

설명

jest.fn()으로 mock 함수를 생성하고, 호출 횟수와 인자, 반환값 등을 검증할 수 있습니다. 의존성을 격리할 때 유용합니다.


4. 모듈 Mocking

개요

외부 모듈이나 API 호출을 가짜 구현으로 대체하여 독립적인 테스트를 수행합니다.

코드 예제

jest.mock('./api');
import { fetchData } from './api';

fetchData.mockResolvedValue({ data: 'test' });

test('displays fetched data', async () => {
  const result = await fetchData();
  expect(result.data).toBe('test');
});

설명

jest.mock()으로 모듈을 모킹하고 mockResolvedValue로 반환값을 지정합니다. 실제 API 호출 없이 테스트할 수 있습니다.


5. 테스트 전후 설정

개요

beforeEach, afterEach 등을 사용하여 각 테스트 전후에 실행될 코드를 정의합니다. 테스트 환경을 초기화할 때 사용합니다.

코드 예제

let database;

beforeEach(() => {
  database = { users: [] };
});

test('adds user to database', () => {
  database.users.push({ id: 1, name: 'Alice' });
  expect(database.users.length).toBe(1);
});

설명

beforeEach는 각 테스트 전에 실행되어 독립적인 테스트 환경을 보장합니다. afterEach, beforeAll, afterAll도 사용 가능합니다.


6. Matcher 활용

개요

다양한 matcher를 사용하여 값을 정밀하게 검증합니다. 객체, 배열, 예외 등 다양한 타입을 검증할 수 있습니다.

코드 예제

test('object matching', () => {
  const user = { name: 'John', age: 30 };
  expect(user).toEqual({ name: 'John', age: 30 });
  expect(user.name).toContain('oh');
  expect(user.age).toBeGreaterThan(25);
});

설명

toBe는 참조 비교, toEqual은 값 비교입니다. toContain, toBeGreaterThan 등 다양한 matcher로 정확한 검증이 가능합니다.


7. 예외 처리 테스트

개요

함수가 예상대로 에러를 발생시키는지 검증합니다. 에러 핸들링 로직을 테스트할 때 필수적입니다.

코드 예제

function divide(a, b) {
  if (b === 0) throw new Error('Division by zero');
  return a / b;
}

test('throws error on division by zero', () => {
  expect(() => divide(10, 0)).toThrow('Division by zero');
});

설명

toThrow matcher를 사용하여 함수가 올바른 에러를 발생시키는지 확인합니다. 함수는 화살표 함수로 감싸야 합니다.


8. Snapshot 테스팅

개요

컴포넌트나 객체의 출력을 저장하고, 이후 테스트에서 변경사항을 자동으로 감지합니다.

코드 예제

function formatUser(user) {
  return `${user.name} (${user.email})`;
}

test('formats user correctly', () => {
  const user = { name: 'Alice', email: 'alice@test.com' };
  expect(formatUser(user)).toMatchSnapshot();
});

설명

toMatchSnapshot()은 첫 실행 시 결과를 저장하고, 이후 실행에서 변경을 감지합니다. UI 컴포넌트 테스트에 특히 유용합니다.


9. 테스트 커버리지

개요

코드의 어느 부분이 테스트되었는지 측정합니다. jest --coverage 명령으로 실행할 수 있습니다.

코드 예제

function processData(data) {
  if (!data) return null;
  if (data.length === 0) return [];
  return data.map(x => x * 2);
}

test('handles all branches', () => {
  expect(processData(null)).toBeNull();
  expect(processData([])).toEqual([]);
  expect(processData([1, 2])).toEqual([2, 4]);
});

설명

모든 분기(if문)를 테스트하여 100% 커버리지를 달성합니다. 커버리지 리포트로 누락된 코드를 찾을 수 있습니다.


10. TDD 실습

개요

Test-Driven Development는 테스트를 먼저 작성하고 구현하는 개발 방식입니다. Red-Green-Refactor 사이클을 따릅니다.

코드 예제

// 1. 실패하는 테스트 작성 (Red)
test('filters even numbers', () => {
  expect(filterEven([1, 2, 3, 4])).toEqual([2, 4]);
});

// 2. 테스트 통과하도록 구현 (Green)
const filterEven = arr => arr.filter(x => x % 2 === 0);

설명

테스트를 먼저 작성하면 요구사항이 명확해지고, 리팩토링 시 안전성이 보장됩니다. 코드 품질이 향상되는 효과가 있습니다.


11. 통합 테스트

개요

여러 모듈이 함께 작동하는지 검증합니다. 실제 사용 시나리오와 유사한 환경에서 테스트합니다.

코드 예제

class UserService {
  constructor(db) { this.db = db; }
  async createUser(name) {
    return this.db.insert({ name, createdAt: Date.now() });
  }
}

test('creates user in database', async () => {
  const mockDb = { insert: jest.fn().mockResolvedValue(1) };
  const service = new UserService(mockDb);
  await service.createUser('Alice');
  expect(mockDb.insert).toHaveBeenCalled();
});

설명

여러 컴포넌트의 상호작용을 테스트합니다. 의존성은 mock으로 대체하여 제어 가능한 환경을 만듭니다.


12. 테스트 조직화

개요

describe 블록으로 관련된 테스트를 그룹화하여 가독성과 유지보수성을 높입니다.

코드 예제

describe('Calculator', () => {
  describe('addition', () => {
    test('adds positive numbers', () => {
      expect(sum(1, 2)).toBe(3);
    });
    test('adds negative numbers', () => {
      expect(sum(-1, -2)).toBe(-3);
    });
  });
});

설명

describe로 테스트를 논리적으로 그룹화하면 테스트 결과를 읽기 쉽고, beforeEach 등을 그룹별로 적용할 수 있습니다.


마치며

이번 글에서는 Testing 기초부터 심화까지 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#Testing #Jest #UnitTest #Mocking #TDD

#Testing#Jest#UnitTest#Mocking#TDD#JavaScript

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.