단위 테스트(Unit Testing)는 코드의 최소 단위(함수, 메서드, 클래스)가 의도대로 동작하는지 검증하는 자동화된 테스트다. 빠른 피드백, 안전한 리팩터링, 문서 역할을 한다.
좋은 단위 테스트 (FIRST 원칙)
- •Fast: 밀리초 단위로 빠르게 실행
- •Isolated: 다른 테스트와 독립적
- •Repeatable: 환경에 상관없이 동일한 결과
- •Self-validating: 수동 확인 없이 Pass/Fail 판정
- •Timely: 코드 작성과 함께 (TDD)
python
# calculator.py
def add(a, b): return a + b
def divide(a, b):
if b == 0:
raise ValueError("0으로 나눌 수 없음")
return a / b
# test_calculator.py
import pytest
from calculator import add, divide
def test_add_positive():
assert add(2, 3) == 5
def test_add_negative():
assert add(-1, -1) == -2
def test_divide_normal():
assert divide(10, 2) == 5.0
def test_divide_by_zero():
with pytest.raises(ValueError, match="0으로 나눌 수 없음"):
divide(10, 0)
# 파라미터화 테스트
@pytest.mark.parametrize("a,b,expected", [
(1, 2, 3),
(-1, 1, 0),
(0, 0, 0),
])
def test_add_parametrize(a, b, expected):
assert add(a, b) == expected
외부 의존성(DB, API, 파일)을 가짜 객체로 대체한다.
python
from unittest.mock import Mock, patch
def test_user_service_get_user():
mock_repo = Mock()
mock_repo.find_by_id.return_value = User(1, "Alice")
service = UserService(mock_repo)
user = service.get_user(1)
assert user.name == "Alice"
mock_repo.find_by_id.assert_called_once_with(1)
# 환경 변수, 외부 함수 패치
with patch('module.requests.get') as mock_get:
mock_get.return_value.json.return_value = {"id": 1}
result = fetch_user(1)
테스트 구조 (AAA 패턴)
python
def test_something():
# Arrange: 준비
user = User(1, "Alice")
service = UserService(MockRepo())
# Act: 실행
result = service.process(user)
# Assert: 검증
assert result.status == "processed"
관련 개념
- •TDD — 테스트 먼저 작성하는 개발 방법론
- •의존성 주입 — Mock 사용을 가능하게 하는 설계
- •리팩터링 — 단위 테스트가 안전망 역할
- •소프트웨어 테스팅 — 단위 테스트가 속하는 넓은 범주