3단계
pytest · fixture · parametrize
25 분
pytest · fixture · parametrize
파이썬 테스트의 사실상 표준. unittest 보다 간결 · 강력.
1. 설치
uv add --dev pytest pytest-asyncio pytest-cov
pyproject.toml:
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
addopts = "-v --tb=short"
2. 첫 테스트
# tests/test_math.py
def test_addition():
assert 1 + 1 == 2
def test_addition_parametrized():
for a, b, expected in [(1, 1, 2), (2, 3, 5), (-1, 1, 0)]:
assert a + b == expected
3. parametrize — 반복 제거
import pytest
@pytest.mark.parametrize("a, b, expected", [
(1, 1, 2),
(2, 3, 5),
(-1, 1, 0),
])
def test_add(a, b, expected):
assert a + b == expected
실패 시 어느 케이스인지 명확히 표시.
4. fixture — 재사용 가능한 셋업
# tests/conftest.py
import pytest
from httpx import AsyncClient
@pytest.fixture
async def client():
from main import app
async with AsyncClient(app=app, base_url="http://test") as c:
yield c
@pytest.fixture
def sample_user():
return {"email": "test@example.com", "name": "Test"}
# tests/test_users.py
async def test_create_user(client, sample_user):
r = await client.post("/users", json=sample_user)
assert r.status_code == 201
함수 인자 이름 = fixture 이름. 자동 의존성 주입.
5. fixture scope
@pytest.fixture(scope="session") # 전체 테스트 세션 1회
def db_engine():
engine = create_engine(...)
yield engine
engine.dispose()
@pytest.fixture(scope="function") # 매 테스트 (기본)
def db_session(db_engine):
with db_engine.connect() as conn:
yield conn
conn.rollback()
비싼 리소스는 session · module scope, 가변 상태는 function scope.
6. async 테스트
import pytest
pytestmark = pytest.mark.asyncio
async def test_async_fn():
result = await async_compute()
assert result == 42
asyncio_mode = "auto" 설정하면 마킹 생략 가능.
7. mocker fixture — pytest-mock
uv add --dev pytest-mock
def test_send_email(mocker):
mock = mocker.patch("app.mail.send_mail")
process_signup("user@example.com")
mock.assert_called_once_with("user@example.com", subject=mocker.ANY)
unittest.mock 를 fixture 로 편하게.
8. coverage
uv run pytest --cov=app --cov-report=term-missing --cov-report=html
htmlcov/index.html 에서 커버되지 않은 라인 시각화.
9. 자주 걸리는 자리
- fixture 이름이 파라미터 이름과 불일치 — 이름 맞춰야 주입됨
- scope 오용 — session scope fixture 가 상태 변경되면 다음 테스트 오염
- async 테스트 동기 실행 —
asyncio_mode = "auto"또는@pytest.mark.asyncio - fixture 의존 순환 — A → B, B → A 금지
10. 빠르게 실행
pytest -x # 첫 실패 시 중단
pytest -k "test_user" # 이름 매칭
pytest --lf # 마지막 실패만 재실행
pytest -n auto # 병렬 (pytest-xdist)
하고픈 말
fixture + parametrize 두 가지가 pytest 를 vitest 보다 한 단계 위로 끌어올립니다. 파이썬 백엔드에서는 거의 필수 도구.
Next
- 04-testcontainers