본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 3. · 49 Views
Testing 기초부터 심화까지 완벽 가이드
소프트웨어 테스팅의 핵심 개념부터 고급 테스팅 패턴까지 다룹니다. 단위 테스트, 통합 테스트, E2E 테스트, Mocking, TDD 등 실무에서 필요한 모든 테스팅 기법을 학습합니다.
들어가며
이 글에서는 Testing 기초부터 심화까지 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- 기본_단위_테스트
- 비동기_코드_테스트
- Mock_함수_활용
- 모듈_Mocking
- 테스트_전후_설정
- Matcher_활용
- 예외_처리_테스트
- Snapshot_테스팅
- 테스트_커버리지
- TDD_실습
- 통합_테스트
- 테스트_조직화
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
이 카드뉴스가 포함된 코스
댓글 (0)
함께 보면 좋은 카드 뉴스
AI 에이전트 신뢰성 완벽 가이드 - 가드레일과 평가 시스템
AI 에이전트가 예상치 못한 행동을 하지 않도록 안전장치를 설계하고, 품질을 체계적으로 평가하는 방법을 배웁니다. 실무에서 바로 적용할 수 있는 가드레일 패턴과 평가 프레임워크를 다룹니다.
Flutter Flame 게임 테스팅과 디버깅 완벽 가이드
Flutter와 Flame 엔진으로 개발한 게임의 품질을 보장하는 테스팅 기법과 디버깅 도구를 다룹니다. 단위 테스트부터 골든 테스트, 크래시 리포팅까지 실무에서 바로 적용할 수 있는 내용을 담았습니다.
테스트 전략 완벽 가이드
초급 개발자를 위한 테스트 전략의 모든 것을 다룹니다. Vitest부터 단위 테스트, 통합 테스트, E2E 테스트까지 실무에서 바로 적용할 수 있는 테스트 작성법을 배워봅니다.
Cron과 Webhooks 완벽 가이드
Node.js 환경에서 자동화의 핵심인 Cron 작업과 Webhooks를 활용하는 방법을 다룹니다. 정기적인 작업 스케줄링부터 외부 서비스 연동까지, 실무에서 바로 적용할 수 있는 자동화 기법을 배워봅니다.
보안 모델 및 DM Pairing 완벽 가이드
Discord 봇의 DM 보안 정책과 페어링 시스템을 체계적으로 학습합니다. dmPolicy 설정부터 allowlist 관리, 페어링 코드 구현까지 안전한 봇 운영의 모든 것을 다룹니다.