Rehberler Uzun Okuma Fixtures

Testleriniz ne kadar güvenilir?

pytest fixture, monkeypatch ve entegrasyon desenleri.

15 Ocak 2026 19 dk okuma
Paylaş
X in

Giriş

pytest, Python ekosisteminin en yaygın test framework'üdür; minimal boilerplate, zengin fixture sistemi ve geniş plugin ekosistemi sunar. Birim testlerin ötesinde entegrasyon testleri, modüllerin gerçek bağımlılıklarla birlikte doğru çalıştığını doğrular.

Bu yazıda fixture scope'ları, conftest.py organizasyonu, unittest.mock ve pytest-mock ile mock'lama, veritabanı ve HTTP istemcisi entegrasyonu ve CI'da test izolasyonunu ele alıyoruz. Flaky testleri azaltmak için deterministik veri ve transaction rollback desenlerine odaklanıyoruz.

pytest Temelleri ve Fixture'lar

pytest test fonksiyonlarını otomatik keşfeder; assert ifadeleri detaylı karşılaştırma çıktısı verir. @pytest.fixture ile paylaşılan kurulum ve söküm tanımlanır. scope parametresi (function, class, module, session) fixture'ın ne sıklıkla yeniden oluşturulacağını belirler.

yield fixture'lar test sonrası temizlik için idealdir: veritabanı bağlantısı açılır, test çalışır, yield sonrası rollback veya kapatma yapılır. autouse=True ile her teste otomatik enjekte edilen fixture'lar ortak konfigürasyon için kullanılır.

import pytest

@pytest.fixture
def db_session():
    session = create_session()
    yield session
    session.rollback()
    session.close()

def test_create_user(db_session):
    user = User(name="Ali")
    db_session.add(user)
    db_session.commit()
    assert user.id is not None

conftest.py ve Test Organizasyonu

conftest.py dosyaları fixture'ları test dizinine göre hiyerarşik paylaşır; tests/conftest.py tüm alt testlerde geçerlidir. tests/integration/ altında ağır entegrasyon testlerini ayırmak, pytest -m 'not integration' ile hızlı birim test döngüsü sağlar.

@pytest.mark.parametrize ile aynı testi çoklu girdiyle çalıştırmak kod tekrarını azaltır. pytest.ini veya pyproject.toml içinde markers, testpaths ve addopts tanımlanır.

  • tests/unit/: hızlı birim testler
  • tests/integration/: DB ve API testleri
  • conftest.py: paylaşılan fixture'lar
  • markers: integration, slow, smoke

Mocking ve monkeypatch

unittest.mock.patch veya pytest-mock'un mocker fixture'ı dış servisleri izole eder. @patch('mymodule.requests.get') ile HTTP çağrısı sahte yanıt döndürür. MagicMock ile dönüş değeri ve yan etki davranışı tanımlanır.

pytest monkeypatch ortam değişkenlerini ve nesne özniteliklerini geçici değiştirir; test bitince otomatik geri alınır. Entegrasyon testlerinde mock'u minimumda tutun; yalnızca kontrol dışı dış sistemleri (ödeme gateway, e-posta) mock'layın, kendi veritabanınızı gerçek kullanın.

def test_fetch_user(mocker):
    mock_get = mocker.patch("app.client.requests.get")
    mock_get.return_value.json.return_value = {"id": 1, "name": "Ali"}
    result = fetch_user(1)
    assert result["name"] == "Ali"
    mock_get.assert_called_once_with("/users/1")

Veritabanı Entegrasyon Testleri

Test veritabanı üretimden ayrı olmalıdır; Docker Compose ile postgres:16 servisi CI'da kaldırılır. SQLAlchemy'de transaction fixture: her test bir transaction içinde çalışır, sonunda rollback edilir; veri birikimi olmaz.

pytest-django ve pytest-asyncio framework'e özel entegrasyon sağlar. Factory Boy veya Faker ile test verisi üretin; sabit ID'lere bağımlı testler kırılgandır. Alembic migration'ları test ortamında da çalıştırılarak şema uyumu doğrulanır.

API ve HTTP Entegrasyon Testleri

FastAPI TestClient veya httpx.AsyncClient ile uygulama sunucusu açmadan endpoint test edilir. Starlette'nin TestClient'ı ASGI uygulamasını doğrudan çağırır. Gerçek TCP bağlantısı gerekiyorsa pytest ile subprocess'te uvicorn başlatılabilir.

responses veya httpx mock transport ile dış API bağımlılıkları simüle edilir. Contract test (Pact) ile tüketici ve sağlayıcı API sözleşmesi doğrulanır; mikroservis mimarilerinde regresyonu erken yakalar.

from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_health():
    response = client.get("/health")
    assert response.status_code == 200
    assert response.json() == {"status": "ok"}

CI, Coverage ve Flaky Testler

pytest --cov=app --cov-report=xml coverage raporu üretir; %100 hedefi yerine kritik yolları kapsamak daha gerçekçidir. pytest-xdist ile paralel test (-n auto) süreyi kısaltır; paylaşılan fixture'ların scope'una dikkat edin.

Flaky testler genelde zaman, sıra veya paylaşılan durum kaynaklıdır. pytest-rerunfailures geçici hatalarda yeniden dener; kök nedeni çözmeden kalıcı çözüm değildir. Testler arası izolasyon ve sabit seed (random.seed) kullanın.

  1. Her test bağımsız ve tekrarlanabilir olsun
  2. Entegrasyon testlerini marker ile ayırın
  3. CI'da gerçek servisler veya testcontainers kullanın
  4. Flaky testleri izole edip düzeltin, bastırmayın

Sonuç

pytest ile iyi organize edilmiş entegrasyon testleri, refactor güvenini ve deploy hızını artırır. Fixture hiyerarşisi, doğru mock sınırları ve izole test veritabanı üçlüsü sürdürülebilir bir test süitinin temelidir.

Test piramidini koruyun: çoğunluk hızlı birim test, az sayıda kritik entegrasyon testi. Yeni özellik eklerken önce başarısız test yazmak (TDD) uzun vadede regresyon maliyetini düşürür.