codingstairs
노트에듀라이프연락
⌕검색⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

연락하기

로그인 없이도 보낼 수 있어요. 답변이 필요하면 이메일을 함께 적어 주세요.

  • 익명 폼으로 의견 남기기 →
  • ✉ warragon112@gmail.com
  • 카카오톡 오픈채팅 ↗

© 2026 codingstairs

  • 노트
  • 에듀
  • 검색
  • 라이프
  • 연락
  • 약관
  • RSS
  • GitHub
에듀›테스트 전략과 품질 게이트›3단계

3단계

pytest · fixture · parametrize

0회 조회

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

← 2단계

vitest 기본 + mock 패턴

4단계 →

testcontainers